Wie führe ich ein Programm mit einem anderen Arbeitsverzeichnis als das aktuelle aus der Linux-Shell aus?


352

Wie starte ich mit einer Linux-Shell ein Programm mit einem anderen Arbeitsverzeichnis als dem aktuellen Arbeitsverzeichnis?

Zum Beispiel habe ich eine Binärdatei helloworld, die die Datei hello-world.txtim aktuellen Verzeichnis erstellt .

Diese Datei befindet sich im Verzeichnis /a.

Derzeit bin ich im Verzeichnis /b. Ich möchte mein Programm starten ../a/helloworldund das hello-world.txtirgendwo in einem dritten Verzeichnis abrufen /c.


5
Ich habe die schwierige Methode entdeckt, mit der sudas Arbeitsverzeichnis auf das von Ihnen angegebene Ausgangsverzeichnis des Benutzers zurückgesetzt wird, bevor -cBefehle ausgeführt werden. Das war sehr hilfreich für mich.
— Patrick M

Antworten:


561

Rufen Sie das Programm folgendermaßen auf:

(cd /c; /a/helloworld)

Die Klammern bewirken, dass eine Unterschale erzeugt wird. Diese Sub-Shell ändert dann ihr Arbeitsverzeichnis in /cund wird dann helloworldvon ausgeführt /a. Nach dem Beenden des Programms wird die Sub-Shell beendet und Sie kehren zu Ihrer Eingabeaufforderung der übergeordneten Shell in dem Verzeichnis zurück, in dem Sie begonnen haben.

Fehlerbehandlung: Um zu vermeiden, dass das Programm ausgeführt wird, ohne das Verzeichnis geändert zu haben, z. B. wenn Sie falsch geschrieben haben /c, machen Sie die Ausführung von helloworldBedingungen abhängig:

(cd /c && /a/helloworld)

Reduzieren der Speichernutzung: Um zu vermeiden, dass die Subshell während der Ausführung von Hello World Speicher verschwendet, rufen Sie helloworldvia exec auf:

(cd /c && exec /a/helloworld)

[Vielen Dank an Josh und Juliano für die Tipps zur Verbesserung dieser Antwort!]


1
Gibt es eine Möglichkeit, Argumente an diese Shell zu übergeben? Wie in $ 1 und $ 2?
— Finiteloop

2
@segfault: Die Subshell hat vollständigen Zugriff auf den umgebenden Bereich.
— David Schmitt

Scheint, als ob es sich sowieso vorübergehend in diesem Verzeichnis befindet, nicht wahr?
— Dhein

1
Sie können alle Argumente übergeben, indem Sie $ *, $ @ oder "$ @" ausführen (wenn Sie möchten, dass Argumente doppelte Anführungszeichen berücksichtigen)
— Marcel Valdez Orozco

1
Wird es funktionieren, wenn ich diese Zeile zu /etc/rc.d/rc.local hinzufüge?
— Pratik Patil

95

Ähnlich wie die Antwort von David Schmitt und der Vorschlag von Josh, lässt jedoch keinen Shell-Prozess laufen:

(cd /c && exec /a/helloworld)

Diese Methode ähnelt eher der Ausführung von Befehlen auf der Shell. Um den praktischen Unterschied zu erkennen, müssen Sie ps efmit jeder Lösung von einer anderen Shell aus laufen .



25

Eine Option, für die keine Subshell erforderlich ist und die zum Bash integriert ist

(pushd SOME_PATH && run_stuff; popd)

Demo:

$ pwd
/home/abhijit
$ pushd /tmp # directory changed
$ pwd
/tmp
$ popd
$ pwd
/home/abhijit

1
Ein ähnlicher Vorschlag wurde unten von Sahil gemacht. Es funktioniert nicht, wenn der Befehl fehlschlägt. Bedenken Sie pushd SOME_PATH && run_stuff && popd: Wenn run_stuff fehlschlägt, wird popd nicht ausgeführt.
— Anton Daneyko

Späte Antwort, das hängt von den Einstellungen der Bash-Datei ab. Bash kann die Ausführung von Befehlen auch nach einem fehlgeschlagenen Befehl fortsetzen (im Gegensatz zur Verwendung von &&). Es kann jedoch so eingestellt werden, dass dies nicht set -ein der Datei verwendet wird, und dies würde dann fehlschlagen popd.
— Loren

8
Dennoch denke ich, pushd "${SOME_PATH}" && run_stuff; popdist besser als die aktuelle Antwort, da die Pushd / Popd-Semantik speziell für diese Situation entwickelt wurde, in ein Verzeichnis zu wechseln und dann zum ursprünglichen zurückzukehren.
— Marcel Valdez Orozco

Wie funktioniert es als Alias ​​definiert und ich muss einen Parameter übergeben?
— DrB

Ich denke, Sie müssten ein Shell-Skript schreiben, an das Sie den Parameter übergeben würden, der die Reihe von Befehlen ausführen würde, da Sie keinen Parameter in der Mitte eines Alias ​​übergeben können. Wenn Sie Hilfe beim Schreiben benötigen, sollten Sie eine separate Frage stellen und auf diese verweisen. Sobald Sie das Shell-Skript haben, können Sie einen Alias ​​schreiben, um Ihr neues Skript aufzurufen.
— Loren

19
sh -c 'cd /c && ../a/helloworld'

1
Verwendet dies für Jexec von FreeBSD, um einen Befehl im Gefängnis im angegebenen Arbeitsverzeichnis auszuführen.
— Marián Černý

11

Ich denke immer, UNIX-Tools sollten als Filter geschrieben werden, Eingaben von stdin lesen und Ausgaben in stdout schreiben. Wenn möglich, können Sie Ihre helloworld-Binärdatei ändern, um den Inhalt der Textdatei in stdout anstatt in eine bestimmte Datei zu schreiben. Auf diese Weise können Sie die Shell verwenden, um Ihre Datei überall zu schreiben.

$ cd ~ / b

$ ~ / a / helloworld> ~ / c / helloworld.txt


6
+1 für Recht, obwohl die Antwort nur am Rande eine Antwort ist.
— David Schmitt

8

Ändern Sie einfach das letzte "&&" in ";" und es wird zurückgeschickt, egal ob der Befehl fehlschlägt oder erfolgreich ist:

cd SOME_PATH && run_some_command ; cd -

4

Eine Möglichkeit, dies zu tun, besteht darin, ein Wrapper-Shell-Skript zu erstellen.

Das Shell-Skript würde das aktuelle Verzeichnis in / c ändern und dann / a / helloworld ausführen. Nach dem Beenden des Shell-Skripts wird das aktuelle Verzeichnis auf / b zurückgesetzt.

Hier ist ein Beispiel für ein Bash-Shell-Skript:

#!/bin/bash
cd /c
/a/helloworld

2

warum nicht einfach halten

cd SOME_PATH && run_some_command && cd -

Der letzte Befehl 'cd' bringt Sie zurück zum letzten pwd-Verzeichnis. Dies sollte auf allen * nix-Systemen funktionieren.


Du schreibst @mezhaka, hätte das berücksichtigen sollen :)
— Sahil

1
Warnung: Wenn dies run_some_commandfehlschlägt, cd -wird es nicht ausgeführt.
— starbeamrainbowlabs

1

Wenn Sie immer möchten, dass es zu / C geht, verwenden Sie beim Schreiben der Datei einen absoluten Pfad.


0

Wenn Sie dies in Ihrem Programm ausführen möchten, würde ich Folgendes tun:

#include <unistd.h>
int main()
{
  if(chdir("/c") < 0 )  
  {
     printf("Failed\n");
     return -1 ;
  }

  // rest of your program...

}

Er möchte dies in einem Shell-Skript und nicht in einem C tun. Außerdem wäre es eine schreckliche Idee, die Binärdatei zu unterverarbeiten.

-1

Geben Sie aus dem aktuellen Verzeichnis den vollständigen Pfad zum Skriptverzeichnis an, um den Befehl auszuführen

/root/server/user/home/bin/script.sh

1
Das ändert das Arbeitsverzeichnis überhaupt nicht - ich denke, Sie beantworten eine andere Frage als die, die gestellt wurde.
— Toby Speight

Kam hierher, um eine Antwort auf die Frage zu finden, die Sie beantwortet haben. Vielen Dank! lol
— kfrncs
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.