Eseguire un comando specifico in una determinata directory senza eseguirne il cd?


42

C'è un modo per eseguire un comando in una directory diversa senza doverlo fare cd? So che potrei semplicemente entrare cde cduscire, ma sono solo interessato alle possibilità di rinunciare ai passaggi aggiuntivi :)


E 'piuttosto banale per fare uno script che fa questo: echo "#!/bin/bash; cd $1; exec $2" > /usr/local/bin/execindirectory; chmod +x /usr/local/bin/execindirectory. Potrebbe essere necessario un piccolo sforzo in più se si desidera effettivamente supportare "tag" di opzioni come -de cose.
LawrenceC,

Come afferma l'utente sconosciuto in una risposta, tutti gli esempi che hai fornito qui e nei commenti sono meglio affrontati da altre soluzioni, quindi non è chiaro se in realtà c'è un problema che deve essere risolto qui. Puoi venire con un esempio migliore?
Caleb,

Risposte:


55

Non so se questo conta, ma puoi creare una subshell:

$ (cd /var/log && cp -- *.log ~/Desktop)

La directory viene modificata solo per quella subshell, in modo da evitare il lavoro necessario in cd -seguito.


2
Questo è quello che faccio di solito.
Adam Byrtek,

Bene, mi ero completamente dimenticato delle sotto-conchiglie, molto utile in questo caso.
Naftuli Kay,

4
Per evitare il caos potenziale, sub fuori il punto e virgola con due e commerciali: $ (cd /var/log && cp *.log ~/Desktop). In questo modo, se la directory non esiste, non vengono eseguiti altri comandi.
Naftuli Kay,

Nota per chiunque sia ingenuo come me: $ all'inizio non fa parte del comando, ma tutto ciò che segue.
Maltronic,

14

Alcuni programmi hanno opzioni con le quali puoi dire loro di chdir (2) stessi (ad esempio GNU tar 's -C/ --directory).

Al di fuori di tali programmi, però, qualcosa dovrà essere chdir . Potresti scrivere e usare una sorta di programma “binario” compilato invece di farlo fare dalla shell, ma probabilmente non produrrebbe molto beneficio.

In un commento in un'altra risposta, hai fornito un esempio:

execindirectory -d /var/log "cp *.log ~/Desktop"

Poiché il *.logpattern viene espanso dalla shell stessa (non da cp ), qualcosa dovrà chdir nella directory prima che una shell valuti il ​​tuo comando.

Se sei solo interessante nell'evitare di dover "tornare indietro", allora puoi usare una subshell per isolare l'effetto del cd dall'istanza della shell di lavoro.

(cd /path/to/dir && some command)

Puoi impacchettarlo in una funzione shell. (Ho lasciato cadere l' -dopzione dal tuo esempio di utilizzo poiché c'è poco senso a questo comando se la directory è in realtà facoltativa.)

runindir() { (cd "$1" && shift && eval "$@"); }

runindir /var/log 'cp *.log ~/Desktop'  # your example
runindir /var/log cp \*.log \~/Desktop  # eval takes multiple args

runindir /var/log cp \*.log ~/Desktop   # it is okay to expand tilde first

2
Mi piace questa soluzione, tranne, personalmente userei pushd / popd
NJ

10

Non compromettere il valore delle risposte fornite da altre persone, ma credo che ciò che vuoi sia questo:

(cd /path/to && ./executable [ARGS])

Nota le parentesi da invocare cdin una sotto-shell.


Io non la penso così. A quanto ho capito, vuole finire nella directory iniziale.
Adam Byrtek,

Oh, ho completamente dimenticato di avvolgerlo nella sotto-shell. Ho corretto la mia risposta, grazie.
alex

4

Ecco qualcosa che dovrebbe farti cdtornare dove eri (usando Bash), dal momento che non dimenticare di farlo sembra essere lo scopo della domanda:

# Save where you are and cd to other dir
pushd /path/to/dir/that/needs/to/be/current/dir

run-your-command

# Get back where you were at the beginning.
popd

(EDIT: versione leggermente più corta, grazie a @ Random832)


1
potresti semplicemente pushd other-dir, piuttosto chepushd .; cd other-dir
Casuale 832,

@ Random832, buon punto!
Bruno,

2

Purtroppo, il tuo esempio:

execindirectory -d /var/log "cp *.log ~/Desktop"

non è necessario modificare la directory, perché

cp /var/log/*.log ~/Desktop

farebbe lo stesso. Non riesci ad avvicinarti al tuo vero problema? Perché potremmo conoscere una soluzione migliore anche per quello.

Un modo complicato per risolvere il tuo problema, che è lontano dall'eleganza della soluzione Michaels, è l'uso di find, che ha un interruttore '-execdir' da eseguire nella directory, dove viene trovato un file. Adottato male al tuo esempio:

find /var/log -maxdepth 1 -type f -name "*.log" -execdir echo cp {} ~/Desktop ";"

Forse è utile per il tuo vero problema. -okdir invece di -execdir ti chiederà di confermare ogni invocazione.

-okdir e -execdir potrebbero aver bisogno dell'installazione di gnu-find, che è generalmente usato su Linux.


1

Che ne dici ./your/path/command.sh?


No, in realtà ho dire qualcosa di simile a quanto segue: execindirectory -d /var/log "cp *.log ~/Desktop".
Naftuli Kay,

Sono perfettamente consapevole che questo non è strettamente necessario, a proposito, mi interessa solo se può effettivamente essere fatto.
Naftuli Kay,
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.