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...
2 Stimmen
Nur ein Verbesserungsvorschlag: Wenn Sie
pushd
(möglicherweise umgeleitet zu>/dev/null
um seine Ausgabe zu unterdrücken) anstelle voncd
können Sie später in das vorherige Verzeichnis zurückkehren mitpopd
.0 Stimmen
Mögliche Duplikate von Warum funktioniert "cd" nicht in einem Bash-Shell-Skript?