247 Stimmen

Wechseln des aktuellen Verzeichnisses aus einem Bash-Skript

Ist es möglich, das aktuelle Verzeichnis aus einem Skript heraus zu wechseln?

Ich möchte ein Dienstprogramm für die Verzeichnisnavigation in der Bash erstellen. Ich habe ein Testskript erstellt, das wie das folgende aussieht:

#!/bin/bash
cd /home/artemb

Wenn ich das Skript über die Bash-Shell ausführe, ändert sich das aktuelle Verzeichnis nicht. Ist es überhaupt möglich, das aktuelle Shell-Verzeichnis von einem Skript aus zu ändern?

2 Stimmen

Nur ein Verbesserungsvorschlag: Wenn Sie pushd (möglicherweise umgeleitet zu >/dev/null um seine Ausgabe zu unterdrücken) anstelle von cd können Sie später in das vorherige Verzeichnis zurückkehren mit popd .

0 Stimmen

3voto

Arun Chettoor Punkte 951

Wir verwenden grundsätzlich cd.. aus jedem Verzeichnis zurückkommen. Ich habe mir überlegt, es einfacher zu machen, indem ich die Anzahl der Verzeichnisse angebe, mit denen Sie jeweils zurückkommen müssen. Sie können dies mit einer separaten Skriptdatei unter Verwendung des Alias-Befehls implementieren. Zum Beispiel:

code.sh

#!/bin/sh
 _backfunc(){
 if [ "$1" -eq 1 ]; then
  cd ..
 elif [ "$1" -eq 2 ]; then
  cd ../..
 elif [ "$1" -eq 3 ]; then
  cd ../../..
 elif [ "$1" -eq 4 ]; then
  cd ../../../..
 elif ["$1" -eq 10]; then
  cd /home/arun/Documents/work
 fi
 }
alias back='_backfunc'   

Nach der Verwendung source code.sh in der aktuellen Shell können Sie mit :

$back 2 

um vom aktuellen Verzeichnis zwei Schritte zurück zu gehen. Ausführlich erklärt über aquí . Dort wird auch erklärt, wie man den Code in ~/.bashrc einfügt, so dass jede neu geöffnete Shell automatisch diesen neuen Alias-Befehl hat. Sie können neue Befehle für bestimmte Verzeichnisse hinzufügen, indem Sie den Code ändern, indem Sie mehr if conditions und unterschiedliche Argumente. Sie können den Code auch aus Git ziehen über aquí .

3voto

Joel Punkte 111

Ich habe ein Skript zum Wechseln des Verzeichnisses erstellt, sehen Sie es sich an: https://github.com/ygpark/dj

2voto

Defcronyke Punkte 551

Dies ist mein derzeitiger Weg, es für Bash zu tun (getestet auf Debian). Vielleicht gibt es einen besseren Weg:

Tun Sie es nicht mit exec bash, zum Beispiel so:

#!/bin/bash
cd $1
exec bash

weil es zwar zu funktionieren scheint, aber nach Sie es ausführen und Ihr Skript beendet ist, befinden Sie sich zwar im richtigen Verzeichnis, aber Sie befinden sich darin in einer Subshell, was Sie bestätigen können, indem Sie Sie können das bestätigen, indem Sie anschließend Strg+D drücken, und Sie werden sehen, dass die Subshell beendet wird, und Sie kehren in Ihr ursprüngliches Verzeichnis zurück.

Dies ist in der Regel kein Zustand, in dem man einen Skriptbenutzer nach Skript zurückkehrt, denn es ist nicht offensichtlich, dass er sich in einer einer Subshell befindet und nun im Grunde zwei Shells geöffnet hat, obwohl er dachte, er hätte nur eine. Er könnte diese Subshell weiter benutzen, ohne es zu merken, und das könnte unbeabsichtigte Folgen haben.

Wenn Sie wirklich wollen, dass das Skript beendet wird und eine Subshell im neuen Verzeichnis offen lässt neuen Verzeichnis offen lassen, sollten Sie die Variable PS1 so ändern, dass der Skriptbenutzer einen visuellen Indikator hat, dass er noch eine Subshell offen hat.

Hier ist ein Beispiel, das ich mir ausgedacht habe. Es besteht aus zwei Dateien, einer outer.sh, die Sie direkt aufrufen, und eine innere.sh, die innerhalb des Skripts outer.sh aufgerufen wird. Das äußere Skript setzt zwei Variablen, ruft dann das innere Skript auf, und Danach gibt es die beiden Variablen als Echo aus (die zweite wurde gerade vom inneren Skript durch das innere Skript geändert). Danach erstellt es eine temporäre Kopie von Datei ~/.bashrc des aktuellen Benutzers, fügt eine Überschreibung für die Variable PS1 sowie eine Aufräumroutine hinzu und führt schließlich exec bash --rcfile, das auf die Datei .bashrc.tmp zeigt, um die Bash mit einer geänderten Umgebung zu initialisieren, einschließlich der geänderten Eingabeaufforderung und der Aufräumroutine Routine.

Nachdem outer.sh beendet wurde, befinden Sie sich in einer Subshell im gewünschten Verzeichnis (in diesem Fall testdir/, in das das Skript inner.sh eingegeben wurde) mit einem visuellen Indikator, der Sie darauf hinweist, und wenn Sie die Subshell verlassen, Wenn Sie die Subshell verlassen, wird die Datei .bashrc.tmp von der Bereinigungsroutine gelöscht, und Sie befinden sich wieder in dem Verzeichnis, in dem Sie begonnen haben.

Vielleicht gibt es einen besseren Weg, aber das ist der beste Weg, den ich finden konnte. in etwa 40 Minuten Experimentierzeit herausfinden konnte:

Datei 1: outer.sh

#!/bin/bash

var1="hello"
var2="world"

source inner.sh

echo $var1
echo $var2

cp ~/.bashrc .bashrc.tmp

echo 'export PS1="(subshell) $PS1"' >> .bashrc.tmp

cat <<EOS >> .bashrc.tmp
cleanup() {
    echo "cleaning up..."
    rm .bashrc.tmp
}

trap 'cleanup' 0
EOS

exec bash --rcfile .bashrc.tmp

Datei 2: inner.sh

cd testdir
var2="bird"

dann laufen:

$ mkdir testdir
$ chmod 755 outer.sh

$ ./outer.sh

sollte er ausgeben:

hello
bird

und lassen Sie dann mit exec bash in Ihre Subshell fallen, aber mit einem geänderten Eingabeaufforderung, die das deutlich macht, etwa so:

(subshell) user@computername:~/testdir$

und wenn Sie Strg-D aus der Subshell heraus drücken, sollte es durch Löschen von eine temporäre Datei .bashrc.tmp im Verzeichnis testdir/

Ich frage mich, ob es einen besseren Weg gibt, als die .bashrc-Datei zu kopieren zu kopieren, um die PS1-Var in der Subshell richtig zu ändern...

0voto

Daniel C. Deng Punkte 1563

Dieser Ansatz ist für mich einfacher.

Nehmen wir an, auf einem persönlichen iMac, auf dem Sie Administrator sind, wird beim Öffnen eines Befehlsfensters unter dem Standardverzeichnis /Users/jdoe das entsprechende Verzeichnis angezeigt: /Users/jdoe/Desktop/Mongo/db.3.2.1/bin.

Dies sind die Schritte, mit denen die Arbeit erledigt werden kann:

  1. vi mongobin, in das ich eintrat: cd /Users/jdoe/Desktop/Mongo/db.3.2.1/bin als erste Zeile.
  2. chmod 755 mongobin
  3. source mongobin
  4. pwd

Voilà!

0voto

Mateusz Piotrowski Punkte 6778

Ich habe auch ein Dienstprogramm namens Ziege die Sie zur leichteren Navigation verwenden können.

Sie können den Quellcode auf folgender Website einsehen GitHub .

Ab dem v2.3.1 el Verwendungsübersicht sieht so aus:

# Create a link (h4xdir) to a directory:
goat h4xdir ~/Documents/dev

# Follow a link to change a directory:
cd h4xdir

# Follow a link (and don't stop there!):
cd h4xdir/awesome-project

# Go up the filesystem tree with '...' (same as `cd ../../`):
cd ...

# List all your links:
goat list

# Delete a link (or more):
goat delete h4xdir lojban

# Delete all the links which point to directories with the given prefix:
goat deleteprefix $HOME/Documents

# Delete all saved links:
goat nuke

# Delete broken links:
goat fix

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X