J'utilise la recherche d'une tâche et j'ai remarqué que lorsque je fais quelque chose comme ça:
find `pwd` -name "file.ext" -exec echo $(dirname {}) \;
cela vous donnera des points uniquement pour chaque match. Lorsque vous remplacez dirname
avec basename
dans cette commande, vous obtenez les noms de chemin complets. Suis-je vissé quelque chose ici ou est-ce que ce comportement attendu? Je suis habitué à basename
vous donnant le nom du fichier (dans ce cas file.ext
) et dirname
vous donnant le reste du chemin.
Considérez le script suivant:
#!/bin/sh
set -x
find `pwd` -name "file.ext" -exec echo $(dirname {}) \;
set -x
Montre comment l'expansion fonctionne et quelle est la commande finale. Lorsqu'il est exécuté, il donne la sortie suivante:
++ pwd
++ dirname '{}'
+ find /home/kibab -name file.ext -exec echo . ';'
Donc, la première chose qui est étendue est le pwd
. Deuxièmement, c'est $(dirname {})
. Le résultat de ces deux commandes est ensuite tombé dans la commande de recherche. Ainsi, vous indiquez à trouver -exec echo .
, Vous voyez donc la sortie attendue.
Lorsque vous remplacez basename
pour dirname
, l'expansion prend toujours des endroits, mais les résultats de l'expansion sont différents:
pwd
est étendu à la voie actuelle. Dans mon exemple ci-dessus, le résultat est /home/kibab
basename {}
Est exécuté. Le résultat de cette commande est {}
.La commande de recherche est exécutée avec les substitutions ci-dessus en place. La commande finale exécutée ressemble à ceci:
find /home/kibab -name '*.png' -exec echo '{}' ';'
Lors de l'inspection de la commande ci-dessus, vous remarquerez que la commande désormais tout simplement tout le dossier de l'ECHO.
Peut-être que tu veux quelque chose comme ça?
find `pwd` -name "file.ext" -printf "%f\n"
Donc, le problème est que $ (...) ou `...` commence une nouvelle coquille avant de faire le remplacement.
Pensez à utiliser Bash -C:
$ find . -name '*.PNG' -exec bash -c 'git mv {} $(dirname {})/$(basename {} .PNG)48.png' \;
Cela renomme n'importe quelle icône sur un repo git à une forme plus standard.
Ici {} est remplacé avant d'exécuter quoi que ce soit, le problème est parti.
Pour cet exemple, TMTOWTDI, mais j'essaie de garder cela simple afin que vous puissiez commencer ce que vous avez vraiment besoin de faire.
vous n'avez pas à appeler DirName () pour chaque fichier trouvé. avec GNU trouver, vous pouvez utiliser -printf
et c'est plus rapide de cette façon
find /path -type f -iname "*.ext" -printf "%h\n"
$(dirname {})
est évalué par la coque avant d'être transmis à find
. Le résultat de cette évaluation est .
, Vous devez donc simplement dire find
d'exécuter echo .
Pour chaque fichier qu'il trouve.
basename {}
Évalue à {}
, Donc avec $(basename {})
substitué pour $(dirname {})
, find
exécutera echo {}
Pour chaque déposer. Cela se traduit par le nom complet de chaque fichier étant écho.
Si vous souhaitez émettre le résultat de dirname
pour chaque fichier trouvé, vous pouvez omettre le echo
:
find `pwd` -name "file.ext" -exec dirname {} \;
Il vous montre les points, car la substitution de processus est évaluée avant que la commande soit réellement exécutée. Vous devez donc transmettre votre commande dans une instance de shell distincte.
Quant à la solution de contournement, utilisez la syntaxe suivante:
find $PWD -name "file.ext" -exec sh -c 'echo $(dirname {})' ';'
Cependant, le moyen le plus simple d'imprimer ou d'exécuter quelque chose dans chaque répertoire est de -execdir
, par exemple.:
find . -name "file.ext" -execdir pwd ';'
Je ne sais pas pourquoi vous obtenez cela, mais essayez ceci:
find `pwd` -name file.ext |xargs -l1 dirname
C'est parce que find
imprime les chemins par rapport au chemin qu'il effectue. Si vous avez essayé cette recherche de /
vous obtiendrez `` pwd\
Pour chaque chemin.