Come posso eseguire un programma con una directory di lavoro diversa dalla corrente, dalla shell di Linux?


352

Utilizzando una shell Linux , come posso avviare un programma con una directory di lavoro diversa dalla directory di lavoro corrente?

Ad esempio, ho un file binario helloworldche crea il file hello-world.txtnella directory corrente .

Questo file si trova all'interno della directory /a.

Attualmente sono nella directory /b. Voglio avviare il mio programma in esecuzione ../a/helloworlde ottenere hello-world.txtda qualche parte in una terza directory /c.


5
Ho scoperto il modo difficile che sureimposta la directory di lavoro sulla home directory dell'utente specificato prima di eseguire qualsiasi -ccomando. Questo mi è stato molto utile.
Patrick M,

Risposte:


561

Chiama il programma in questo modo:

(cd /c; /a/helloworld)

Le parentesi causano la generazione di una sotto-shell. Questa sotto-shell cambia quindi la sua directory di lavoro in /c, quindi viene eseguita helloworldda /a. Una volta terminato il programma, la sotto-shell termina, tornando al prompt della shell genitore, nella directory da cui è stata avviata.

Gestione degli errori: per evitare di eseguire il programma senza aver modificato la directory, ad esempio in caso di errori di ortografia /c, eseguire l'esecuzione di helloworldcondizionale:

(cd /c && /a/helloworld)

Riduzione dell'utilizzo della memoria: per evitare di sprecare la memoria della subshell durante l'esecuzione di Hello World, chiamare helloworldtramite exec:

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

[Grazie a Josh e Juliano per aver dato consigli su come migliorare questa risposta!]


1
Qualche modo per passare argomenti a questa shell? Come in $ 1 e $ 2?
finiteloop,

2
@segfault: la subshell ha accesso completo all'ambito circostante.
David Schmitt,

Sembra che sia temporaneamente in quella directory comunque, non è vero?
Dhein,

1
Puoi passare tutti gli argomenti facendo $ *, $ @ o "$ @" (se vuoi che gli argomenti rispettino le doppie virgolette)
Marcel Valdez Orozco,

1
Funzionerà se aggiungo questa riga a /etc/rc.d/rc.local?
Pratik Patil,

95

Simile alla risposta di David Schmitt , più il suggerimento di Josh, ma non lascia in esecuzione un processo shell:

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

In questo modo è più simile a come si eseguono normalmente i comandi sulla shell. Per vedere la differenza pratica, devi correre ps efda un'altra shell con ogni soluzione.



25

Un'opzione che non richiede una subshell ed è integrata in bash

(pushd SOME_PATH && run_stuff; popd)

demo:

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

1
Un suggerimento simile è stato fatto di seguito da Sahil. Non funziona se il comando non riesce. Considera pushd SOME_PATH && run_stuff && popd: se run_stuff fallisce, allora popd non verrà eseguito.
Anton Daneyko,

Risposta tardiva, dipende dalle impostazioni del file bash. Bash può continuare a eseguire comandi anche dopo un comando non riuscito (diversamente dall'uso di &&), ma può essere impostato per non farlo usando set -enel file e quindi non ci riuscirà popd.
Loren,

8
Tuttavia, penso che pushd "${SOME_PATH}" && run_stuff; popdsia migliore della risposta attuale, poiché la semantica pushd / popd è stata appositamente progettata per questa situazione di andare in qualche directory e poi tornare a quella originale.
Marcel Valdez Orozco,

Come funziona definito come alias e devo passare un parametro?
DrB

Penso che dovresti scrivere uno script di shell a cui passeresti il ​​parametro che eseguirà la serie di comandi in quanto non puoi passare un parametro nel mezzo di un alias. Se hai bisogno di aiuto per scriverlo, dovresti porre una domanda separata e fare riferimento a questa. Una volta che hai lo script della shell, puoi scrivere un alias per chiamare il tuo nuovo script.
Loren,

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

1
Usato per jexec di FreeBSD per eseguire un comando all'interno della jail nella directory di lavoro specificata.
Marián Černý,

11

Penso sempre che gli strumenti UNIX debbano essere scritti come filtri, leggere input da stdin e scrivere output su stdout. Se possibile, è possibile modificare il file binario di helloworld per scrivere il contenuto del file di testo su stdout anziché in un file specifico. In questo modo puoi usare la shell per scrivere il tuo file ovunque.

$ cd ~ / b

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


6
+1 per aver ragione, anche se la risposta è solo una risposta periferica.
David Schmitt,

8

Cambia l'ultimo "&&" in ";" e verrà riavviato, indipendentemente dal fatto che il comando fallisca o abbia esito positivo:

cd SOME_PATH && run_some_command ; cd -

4

Un modo per farlo è quello di creare uno script shell wrapper.

Lo script della shell cambierebbe la directory corrente in / c, quindi eseguirà / a / helloworld. Una volta terminato lo script della shell, la directory corrente torna a / b.

Ecco un esempio di script di shell bash:

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

2

perché non mantenerlo semplice

cd SOME_PATH && run_some_command && cd -

l'ultimo comando 'cd' ti riporterà all'ultima directory pwd. Questo dovrebbe funzionare su tutti i sistemi * nix.


Stai scrivendo @mezhaka, avresti dovuto considerarlo :)
Sahil

1
Avviso: se run_some_commandfallisce, cd -non verrà eseguito.
Starbeamrainbowlabs

1

Se vuoi sempre che vada in / C, usa un percorso assoluto quando scrivi il file.


0

Se vuoi eseguire questo all'interno del tuo programma, farei qualcosa del tipo:

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

  // rest of your program...

}

Vuole farlo in uno script di shell e non in una C. Inoltre, sarebbe un'idea orribile sottoelaborare il file binario.

-1

dalla directory corrente fornire il percorso completo alla directory dello script per eseguire il comando

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

1
Ciò non cambia affatto la directory di lavoro - penso che tu stia rispondendo a una domanda diversa da quella che è stata posta.
Toby Speight,

Sono venuto qui per trovare una risposta alla domanda a cui hai risposto. Grazie! lol
kfrncs,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.