Exécuter une commande spécifique dans un répertoire donné sans y faire référence?

42

Existe-t-il un moyen d'exécuter une commande dans un répertoire différent sans y être cdobligé? Je sais que je pourrais simplement entrer cdet cdsortir, mais je suis simplement intéressé par les possibilités de renoncer aux étapes supplémentaires :)

Naftuli Kay
la source
Il est assez trivial de faire un script qui fait cela: echo "#!/bin/bash; cd $1; exec $2" > /usr/local/bin/execindirectory; chmod +x /usr/local/bin/execindirectory. Vous aurez peut-être besoin de faire un peu plus d'effort si vous voulez qu'il supporte réellement l'option "tags" tels que -dand stuff.
LawrenceC
Comme l'utilisateur-inconnu indique dans une réponse, tous les exemples que vous avez donnés ici et dans les commentaires sont mieux pris en compte par d'autres solutions. Il est donc difficile de savoir s'il existe réellement un problème à résoudre ici. Pouvez-vous trouver un meilleur exemple?
Caleb

Réponses:

55

Je ne sais pas si cela compte, mais vous pouvez créer un sous-shell:

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

Le répertoire n’est modifié que pour ce sous-shell, vous évitez ainsi de devoir travailler plus cd -tard.

Michael Mrozek
la source
2
C'est ce que je fais d'habitude.
Adam Byrtek
Nice, j'avais complètement oublié les sous-coquilles, très pratique dans ce cas.
Naftuli Kay
4
Pour éviter le chaos potentiel, sous le point - virgule par deux esperluette: $ (cd /var/log && cp *.log ~/Desktop). Ainsi, si le répertoire n'existe pas, aucune autre commande n'est exécutée.
Naftuli Kay
Remarque pour les autres aussi naïfs que moi: le $ au début ne fait pas partie de la commande, mais tout après.
Maltronic
14

Certains programmes ont des options avec lesquelles vous pouvez indiquer à chdir (2) eux-mêmes (par exemple, GNU tar-C/ --directory).

En dehors de tels programmes, quelque chose devra chdir . Vous pourriez écrire et utiliser une sorte de programme “binaire” compilé au lieu de le faire par le shell, mais cela ne rapporterait probablement pas beaucoup.

Dans un commentaire d'une autre réponse, vous avez donné un exemple:

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

Comme le *.logmotif est développé par le shell lui-même (pas cp ), il faudra quelque chose à chdir dans le répertoire avant qu'un shell évalue votre commande.

Si vous souhaitez simplement éviter d'avoir à “cd back”, vous pouvez utiliser un sous-shell pour isoler l'effet du cd de votre instance de shell active.

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

Vous pouvez intégrer cela dans une fonction shell. (J'ai abandonné l' -doption de votre exemple d'utilisation car il y a peu d'intérêt pour cette commande si le répertoire est réellement optionnel.)

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
Chris Johnsen
la source
2
J'aime cette solution, sauf que personnellement, j'utiliserais pushd / popd
NJ
10

Ne pas saper la valeur des réponses données par d'autres personnes, mais je crois que ce que vous voulez, c'est ceci:

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

Notez les parenthèses à invoquer cddans un sous-shell.

alex
la source
Je ne pense pas. Si je comprends bien, il veut se retrouver dans le répertoire initial.
Adam Byrtek
Oh, j'ai totalement oublié d'envelopper cela dans une sous-coque. Corrigé ma réponse, merci.
alex
4

Voici quelque chose qui devrait vous permettre de cdretourner où vous étiez (en utilisant Bash), car ne pas oublier de le faire semble être le but de la question:

# 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: version légèrement plus courte, grâce à @ Random832)

Bruno
la source
1
vous pourriez juste pushd other-dir, plutôt quepushd .; cd other-dir
Random832
@ Random832, bon point!
Bruno
2

Malheureusement, votre exemple:

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

n'a pas besoin de changement dans le répertoire, car

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

ferait la même chose. Ne pouvez-vous pas vous rapprocher de votre vrai problème? Parce que nous pourrions connaître une meilleure solution pour cela aussi.

Un moyen compliqué de résoudre votre problème, qui est loin de l'élégance de la solution de Michaels, est l'utilisation de find, qui dispose d'un commutateur '-execdir' à exécuter dans le répertoire où se trouve un fichier. Mal adopté à votre exemple:

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

Peut-être que c'est utile pour votre vrai problème. -okdir au lieu de -execdir vous demandera de confirmer chaque invocation.

-okdir et -execdir peuvent nécessiter l’installation de gnu-find, généralement utilisé sous Linux.

Utilisateur inconnu
la source
1

Que diriez- ./your/path/command.shvous

dictateur
la source
Non, je voulais dire quelque chose comme ce qui suit: execindirectory -d /var/log "cp *.log ~/Desktop".
Naftuli Kay
Je suis parfaitement conscient du fait que ce n'est pas strictement nécessaire, d'ailleurs, je m'intéresse uniquement à ce que cela puisse être fait.
Naftuli Kay