Jak uruchomić program z innym katalogiem roboczym niż bieżący, z powłoki Linux?

351

Używać powłoki Linux , jak uruchomić program z innym katalogiem roboczym niż bieżący katalog roboczy?

Na przykład mam plik binarny, helloworldktóry tworzy plik hello-world.txtw bieżącym katalogu .

Ten plik znajduje się w katalogu /a.

Obecnie jestem w katalogu /b. Chcę uruchomić mój program ../a/helloworldi znaleźć hello-world.txtgdzieś w trzecim katalogu /c.

Anton Daneyko
źródło
5
Odkryłem twardy sposób, który suresetuje katalog roboczy do katalogu domowego użytkownika określonego przed uruchomieniem jakichkolwiek -cpoleceń. To było dla mnie bardzo pomocne.
Patrick M

Odpowiedzi:

560

Wywołaj program w następujący sposób:

(cd /c; /a/helloworld)

Nawiasy powodują odrodzenie podpowłoki. Ta podpowłoka następnie zmienia katalog roboczy na /c, a następnie wykonuje helloworldz /a. Po wyjściu z programu podpowłoka kończy działanie, co powoduje powrót do monitu powłoki nadrzędnej w katalogu, w którym został uruchomiony.

Obsługa błędów: Aby uniknąć uruchamiania programu bez zmiany katalogu, np. W przypadku błędnej pisowni /c, wykonaj helloworldwarunek:

(cd /c && /a/helloworld)

Zmniejszenie zużycia pamięci: aby uniknąć marnowania pamięci podpowłoki podczas wykonywania hello world, zadzwoń helloworldprzez exec:

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

[Podziękowania dla Josha i Juliano za udzielenie wskazówek na temat poprawy tej odpowiedzi!]

David Schmitt
źródło
1
Jakiś sposób przekazać argumenty do tej powłoki? Jak w 1 $ i 2 $?
finiteloop
2
@segfault: podpowłoka ma pełny dostęp do otaczającego zakresu.
David Schmitt
Wygląda na to, że i tak jest tymczasowo w tym katalogu, prawda?
dhein
1
Możesz przekazać wszystkie argumenty, wykonując $ *, $ @ lub „$ @” (jeśli chcesz, aby argumenty szanowały podwójne cudzysłowy)
Marcel Valdez Orozco
1
Czy to zadziała, jeśli dodam tę linię do /etc/rc.d/rc.local?
Pratik Patil
95

Podobne do odpowiedzi Davida Schmitta oraz sugestii Josha, ale nie pozostawia uruchomionego procesu powłoki:

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

Ten sposób jest bardziej podobny do tego, jak zwykle uruchamiasz polecenia w powłoce. Aby zobaczyć praktyczną różnicę, musisz uruchomić ps efz innej powłoki z każdym rozwiązaniem.

Juliano
źródło
Bash manual buildins exec
Antonios Hadjigeorgalis
25

Opcja, która nie wymaga podpowłoki i jest wbudowana w bash

(pushd SOME_PATH && run_stuff; popd)

Próbny:

$ pwd
/home/abhijit
$ pushd /tmp # directory changed
$ pwd
/tmp
$ popd
$ pwd
/home/abhijit
Loren
źródło
1
Podobną sugestię przedstawił poniżej Sahil. Nie działa, jeśli polecenie się nie powiedzie. Zastanów się pushd SOME_PATH && run_stuff && popd- jeśli run_stuff zawiedzie, to popd nie zostanie wykonany.
Anton Daneyko,
Późna odpowiedź, która zależy od ustawień pliku bash. Bash może kontynuować wykonywanie poleceń nawet po nieudanym poleceniu (w przeciwieństwie do używania &&), ale można ustawić, aby nie robił tego przy użyciu set -epliku, a wtedy nie będzie popd.
Loren,
8
Mimo to myślę, że pushd "${SOME_PATH}" && run_stuff; popdjest lepsza niż obecna odpowiedź, ponieważ semantyka pushd / popd została zaprojektowana specjalnie do tej sytuacji, gdy wchodzę do jakiegoś katalogu, a potem wracam do pierwotnego.
Marcel Valdez Orozco
Jak to działa jako zdefiniowane jako alias i muszę przekazać parametr?
DrB.
Myślę, że musisz napisać skrypt powłoki, do którego przekazałeś parametr, który wykonałby serię poleceń, ponieważ nie możesz przekazać parametru w środku aliasu. Jeśli potrzebujesz pomocy w napisaniu tego, powinieneś zadać osobne pytanie i odnieść się do tego. Po utworzeniu skryptu powłoki możesz napisać alias, aby wywołać nowy skrypt.
Loren
19
sh -c 'cd /c && ../a/helloworld'
Mihi
źródło
1
Wykorzystano to dla jexec FreeBSD w celu wykonania polecenia w więzieniu w określonym katalogu roboczym.
Marián Černý
11

Zawsze uważam, że narzędzia UNIX powinny być zapisywane jako filtry, czytać dane wejściowe ze standardowego wejścia i zapisywać dane wyjściowe na standardowe wyjście. Jeśli to możliwe, możesz zmienić swój plik binarny helloworld, aby zapisywał zawartość pliku tekstowego na standardowe wyjście, a nie na określony plik. W ten sposób możesz użyć powłoki, aby zapisać plik w dowolnym miejscu.

$ cd ~ / b

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

Luther Blisset
źródło
6
+1 za rację, chociaż odpowiedź jest tylko peryferyjną odpowiedzią.
David Schmitt
8

Po prostu zmień ostatnie „&&” na „;” i odeśle CD bez względu na to, czy polecenie zakończy się niepowodzeniem, czy pomyślnie:

cd SOME_PATH && run_some_command ; cd -
Johnnybravo
źródło
4

Jednym ze sposobów jest utworzenie skryptu powłoki opakowania.

Skrypt powłoki zmieniłby bieżący katalog na / c, a następnie uruchomił / a / helloworld. Po zakończeniu skryptu powłoki bieżący katalog powraca do / b.

Oto przykładowy skrypt powłoki bash:

#!/bin/bash
cd /c
/a/helloworld
Jin Kim
źródło
2

dlaczego nie uprościć tego

cd SOME_PATH && run_some_command && cd -

ostatnia komenda „cd” zabierze cię z powrotem do ostatniego katalogu pwd. Powinno to działać na wszystkich systemach * nix.

Sahil
źródło
Piszesz @mezhaka, powinienem był to wziąć pod uwagę :)
Sahil
1
Ostrzeżenie: jeśli run_some_commandzawiedzie, cd -nie zostanie wykonane.
starbeamrainbowlabs
1

Jeśli zawsze chcesz, aby przechodził do / C, użyj bezwzględnej ścieżki podczas zapisywania pliku.

Tom Ritter
źródło
0

Jeśli chcesz to zrobić w swoim programie, zrobiłbym coś takiego:

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

  // rest of your program...

}
Harold
źródło
On chce to zrobić w skrypcie powłoki, a nie w C. Także przerobienie pliku binarnego byłoby okropnym pomysłem.
-1

z bieżącego katalogu podaj pełną ścieżkę do katalogu skryptów, aby wykonać polecenie

/root/server/user/home/bin/script.sh
Ravi Bhushan
źródło
1
To wcale nie zmienia katalogu roboczego - myślę, że odpowiadasz na inne pytanie niż zadane.
Toby Speight,
Przyszedł tutaj, aby znaleźć odpowiedź na pytanie, na które odpowiedziałeś. Dzięki! lol
kfrncs