Comment utiliser `find -exec` pour exécuter la commande dans le répertoire du fichier trouvé (pas le répertoire courant)?

15

Disons que je suis dans un répertoire qui a des sous - répertoires, dir1, dir2et dir3. Chacun de ces répertoires a un fichier fooet je voudrais exécuter la même commande sur chacun foodans chacun des répertoires et que cette commande soit exécutée à l'intérieur de ce répertoire.

Si je devais le faire "à la main", cela ressemblerait à ceci:

cd dir1
(execute on foo)
cd ../dir2
(execute on foo)
cd ../dir3
(execute on foo)

Il est impératif que la commande soit exécutée à partir de chacun des répertoires . fooest un script de planification par lots (pour HTCondor, si vous voulez savoir) et doit être exécuté à partir de chaque sous-répertoire afin que la sortie des exécutions démarrées par les scripts de planification se retrouve dans chaque sous-répertoire.

La question " Trouver un fichier et exécuter une commande dans le répertoire du fichier ", pour autant que je sache, ne répond pas à ma question. La première réponse à cette question est plus une solution de contournement qui ne fonctionnera pas dans mon cas, et la deuxième réponse n'a pas suffisamment d'explication pour que je sache comment l'utiliser.

NeutronStar
la source
@roaima, veuillez expliquer en quoi il s'agit d'un doublon. La première réponse de cette question ne pas me aider, il est plus d'un travail autour, et la seconde réponse ne fait pas de sens pour moi. Il me faut plus d'explications pour savoir comment l'utiliser.
NeutronStar

Réponses:

23

En supposant que votre findsupport, utilisez l' -execdiroption au lieu de-exec

find * -name 'foo' -execdir pwd \;

Si ce n'est pas le cas, veuillez fournir des détails sur votre plate-forme et / ou distribution (le cas échéant).

roaima
la source
Lorsque vous commencez à appuyer sur "find: Le chemin relatif './node_modules/.bin' est inclus dans la variable d'environnement PATH": askubuntu.com/questions/621132/…
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
Désolé si je peux l'écrire comme ça, mais -execdir (sur Ubuntu) est de la merde, car il ne vous donne pas {}, mais le parent de {}.
uav
1
@uav sans connaître votre cas d'utilisation, je ne peux pas vous aider. Mais en réponse à votre grognement, la documentation indique clairement " J'aime -exec, mais la commande spécifiée est exécutée à partir du sous-répertoire contenant le fichier correspondant ".
roaima
Oui, c'est un cas spécial si vous recherchez -type d (= répertoire) et qu'il n'est pas optimal.
uav
Sans connaître votre cas d'utilisation, je ne peux pas vous aider.
roaima
3

En supposant que vous savez exactement dans quels répertoires exécuter votre commande,

for dir in dir1 dir2 dir3; do
    ( cd "$dir" && somecommand foo )
done

ou, en boucle sur les foofichiers,

for foo in */foo; do
  ( cd "${foo%/*}" && somecommand foo )
done

Le sous-shell empêche le cdd'affecter le répertoire de travail du reste du script. La ${foo%/*}substitution de paramètres se développe jusqu'au nom du répertoire où réside le foofichier (en supprimant tout après le dernier /dans la valeur de $foo).

Utiliser standard findpour faire la même chose (dans le cas où les foofichiers peuvent vivre au fond d'une structure de répertoire):

find . -type f -name foo -exec sh -c '
    for foo do
        ( cd "${foo%/*}" && somecommand foo )
    done' sh {} +

En mots: recherchez tous les fichiers normaux appelés "foo" n'importe où dans le répertoire courant ou ci-dessous et donnez leurs chemins d'accès à ce script shell par lots. Le script shell doit itérer sur les chemins d'accès donnés, changer de répertoire pour la partie répertoire de chaque chemin d'accès et si cela réussit, exécuter somecommand foo.

Pour une solution qui utilise le non standard -execdir, voir la réponse de roaima . Sa réponse adaptée à mon exemple:

find . -type f -name foo -execdir somecommand foo ';'
Kusalananda
la source