Skript zum Wechseln des aktuellen Verzeichnisses (cd, pwd)

44

Ich möchte ein Skript ausführen, um einfach das aktuelle Arbeitsverzeichnis zu ändern:

#!/bin/bash
cd web/www/project

Aber nachdem ich es ausgeführt habe, bleibt die aktuelle pwd unverändert! Wie kann ich das machen?

Sony Santos
quelle

Antworten:

63

Es ist ein erwartetes Verhalten und wurde bereits mehrmals diskutiert.

Das Skript wird in einer Subshell ausgeführt und kann das Arbeitsverzeichnis der übergeordneten Shell nicht ändern. Seine Effekte gehen verloren, wenn es beendet ist.

Um Verzeichnis wechseln permanent sollten Sie beziehen das Skript, wie in

. ./script
Enzotib
quelle
8
@Sony: Beachten Sie, dass Sie verwenden sollten return, um aus einem Skript zu entkommen, das auf diese Weise erstellt wurde, nicht exit- sie ähneln Shell-Funktionen und exitbeenden die Shell, die das Skript erstellt hat.
Charles Stewart
@CharlesStewart Tatsächlich kenne ich mich mit Quellenskripten nicht aus. Danke!
Sony Santos
5
ist source ./scriptdas selbe
Amyassin
2
@amyassin: ja, es ist
Enzotib
2
1. .und sourcesind gleich in bash. 2. Der ./Dateiname muss nicht vor dem Dateinamen stehen, wenn er sich im selben Verzeichnis befindet. Es ist in . script
Ordnung,
19

Erstellen Sie für kleine Aufgaben wie diese einen Alias, anstatt ein Skript zu erstellen.

$ alias cdproj='cd /dir/web/www/proj'

Sie sollten dies zu Ihrer .bashrcDatei hinzufügen , wenn Sie dies für jede interaktive Shell festlegen möchten.

Jetzt können Sie dies als ausführen $ cdproj.

Sachin Divekar
quelle
1
Sie können das Skript auch veranlassen, die auszuführenden Befehle zu wiederholen und diese Befehle dann mit eval `./script` oder eval $(./script)auszuführen. Dies ist ein gängiger Ansatz für Befehle, die die Umgebung der aufrufenden Shell aktualisieren müssen.
Keith Thompson
2
Seien Sie einfach sehr vorsichtig, was Sie ausgeben, wenn Sie den evalAnsatz wählen.
jw013
13

Verwenden Sie exec basham Ende

Ein Bash-Skript kann in seiner aktuellen Umgebung oder in der seiner untergeordneten, jedoch niemals in seiner übergeordneten Umgebung ausgeführt werden.

Diese Frage wird jedoch häufig gestellt, weil man nach der Ausführung eines Bash-Skripts aus einem anderen Verzeichnis an der Bash-Eingabeaufforderung in einem bestimmten Verzeichnis belassen werden möchte .

Wenn dies der Fall ist, führen Sie am Ende des Skripts einfach eine untergeordnete Bash-Instanz aus:

#!/usr/bin/env bash
cd desired/directory
exec bash

Dadurch wird eine neue Unterschale erstellt. Geben Sie ein exit, um zur ersten Shell zurückzukehren, in der das Skript ursprünglich gestartet wurde.

Serge Stroobandt
quelle
Es ist besser, das Skript nur als Quelle zu verwenden, da dies in der akzeptierten Antwort execals letzte Möglichkeit eines Schurken gilt. :)
neuronet
1
dieser trick funktioniert nicht in debian 9 stretch.
vdegenne
3
Das ist der falsche Weg!
Dennis Williamson
3
Da niemand die Probleme detailliert beschrieben hat (ich sehe Sie an, @Dennis): (1) Jedes Mal, wenn Sie dies ausführen, wird ein neuer, beständiger Bash-Prozess erstellt. Tun Sie es zehn- oder zwanzigmal in einer Sitzung, und Sie haben 11 bis 21 Bash-Prozesse aufgestapelt. Dies kann die Leistung beeinträchtigen. Wenn Sie versuchen, die Sitzung durch Eingabe exit(oder Strg + D) sauber zu beenden , müssen Sie dies 11 bis 21 Mal tun. (2) Ein weiterer Nachteil der Verwendung eines ausführbaren Skripts besteht darin, dass Sie beim Festlegen von Shell-Optionen (z. B.  dotgloboder  globstar) in Ihrer interaktiven Shell-Sitzung diese verlieren, da Sie eine neue Shell starten.
G-Man sagt, dass Monica
1
Sehr schöne Lösung! Ich habe meinen Alias ​​in bash_profile umgeschrieben, sodass es sich jetzt um ein Skript handelt, das in einer separaten Datei gespeichert ist. Ich verwende das Skript, um zu einem neu erstellten temporären Ordner zu wechseln. Und jetzt ist es noch einfacher, eine temporäre Bash-Sitzung abzuhalten. SRP in Aktion! Vielen Dank!
artyom.razinov
8

Während es Antworten gibt, die genau die gewünschte Aktion ausführen, besteht eine Standardmethode für diesen Zweck darin, eine symbolische Verknüpfung zu erstellen:

ln -s ~/web/www/project proj   #use full path to dir!

Dann könnten Sie cddas Verzeichnis mit dem Namen proj:

cd proj

Diese Methode ist flexibler, da Sie unter Verwendung des Kurznamens auf Dateien zugreifen können, ohne cd:

ls proj/   #note the endslash!
vim proj/file.x
corvinus
quelle
4

Wenn Sie zwischen weit entfernten Verzeichnissen im Dateisystem wechseln. Ich werde Autojump empfehlen .

stnly
quelle
4

Je nachdem, was Sie tun möchten, kann eine andere Lösung darin bestehen, eine Funktion anstelle eines Skripts zu erstellen.

Beispiel:

Erstellen Sie eine Funktion in einer Datei, sagen wir /home/aidin/my-cd-script:

function my-cd() {
  cd /to/my/path
}

Fügen Sie es dann in Ihre bashrcoder zshrcDatei ein:

# Somewhere in rc file
source /home/aidin/my-cd-script

Jetzt können Sie es wie einen Befehl verwenden:

$ my-cd
Hilfe bei der
quelle
0

Warum nicht "exec" verwenden, um genau das zu tun, was ich mir wünsche?

#!/bin/bash

cd someplace
exec bash

~/someplace
paul
quelle
1
Hüten Sie sich vor Dingen, die zu sein scheinen , was Sie wollen. (Ein riesiges Holzpferd! Genau das, was ich wollte!) Jedes Mal, wenn Sie dies ausführen, wird ein neuer, beständiger Bash-Prozess erstellt. Tun Sie es zehn- oder zwanzigmal in einer Sitzung, und Sie werden 11 bis 21 Bash-Prozesse hintereinander haben. Dies kann die Leistung beeinträchtigen. Wenn Sie versuchen, die Sitzung durch Eingabe exit(oder Strg + D) sauber zu beenden , müssen Sie dies 11 bis 21 Mal tun.
G-Man sagt, dass Monica
Ich konnte definitiv sehen, wo das ein Problem sein würde. Für mich, obwohl ich es einmal benutze, die Arbeit mache, die ich brauche und dann verlasse. Wenn das der einzige Nachteil ist, kann ich damit leben. Wenn es andererseits eine bessere Lösung gibt, bin ich bereit, sie mir anzusehen.
Paul
Aidins Antwort auf diese Frage unter Verwendung einer Shell-Funktion und Sachin Divekars Antwort unter Verwendung eines Alias ​​sind (IMO) bessere Lösungen als die Verwendung eines Skripts. PS Ein weiterer Nachteil der Verwendung eines Skripts besteht darin, dass Sie beim Festlegen von Shell-Optionen (z. B.  dotgloboder  globstar) diese verlieren, da Sie eine neue Shell starten. … (Fortsetzung)
G-Man sagt, dass Monica
(Fortsetzung) ... PPS Ich habe gerade bemerkt, dass Sie im Grunde genommen die Antwort von Serge Stroobandt wiederholen und sagen: „Warum nicht?“ Bei  Stack Exchange erwarten wir, dass Antworten neue Ideen und / oder Informationen liefern und nicht nur diskutieren Andere Antwort.
G-Man sagt, dass Monica
-1

Sie können dies mit einer Funktion oder mit && tun. In den folgenden Beispielen wird Zabbix installiert und eine Datei mit einer Zeile darin erstellt.

Ex:

#!/bin/bash

# Create Function:
installZabbix(){
    cd /usr/src/zabbix-4.2.4;
    ./configure --enable-agent;
    make install;
    cd /usr/src/;
    >file;
    echo "Hi, this is a file." >>file;
}

# Call the function:
installZabbix

oder:

#!/bin/bash
cd /usr/src/zabbix-4.2.4 && ./configure --enable-agent && make install && cd /usr/src && >file && echo "Hi, this is a file." >>file
Raul Chiarella
quelle