2012-12-12 4 views
3

Comment lancer une sous-commande dans l'exec de find? Par exemple, si je veux obtenir le nom de fichier uniquement à partir du chemin complet et l'imprimer, je tireraient,Comment exécuter une sous-commande à l'intérieur de find exec

find ./ -name "*.csv" -exec echo $(basename {}) \; 

où l'écho est commande parent de commande enfant basename.

Mais le résultat est le même que cela,

find ./ -name "*.csv" -exec echo {} \; 

Que dois-je faire?

Répondre

0

Comme toujours, appelez un shell pour l'exécuter.

find ... -exec bash -c "... $1 ..." subshell {} \; 
+0

thnx. m très naïf à la sous-couche. est-ce que j'ai un exemple? – JohnG

0

@ Ignacio est de tout à fait correct, albiet biaisé vers une enveloppe spécifique au lieu de suggérer un shell standard POSIX ....

Cependant, ce que vous essayez de faire est beaucoup plus efficace fait avec filtre. C'est à dire. vous essayez de trouver un moyen d'avoir find transformer chaque chemin d'accès qu'il est sur le point d'imprimer, mais cela provoque un fork pour un processus shell pour chaque nom de fichier qu'il correspond! Pour être plus efficace, vous devriez plutôt essayer de trouver un moyen de transformer la liste des noms de chemins que find pourrait produire dans le formulaire que vous souhaitez voir, et de le faire avec un seul processus supplémentaire. Par exemple, si tout ce que vous voulez voir est le nom de base (c'est-à-dire le nom de fichier final) de chaque chemin, vous pouvez le faire trivialement avec une commande sed relativement simple que vous pouvez rediriger vers find la liste souhaitée des noms:

sed '/^[^/]*$/p;s/.*\/\([^/]*\)$/\1/p' 
+0

bien greg, merci pour la réponse. Je veux utiliser le nom de base comme premier argument d'une autre commande qui devrait s'exécuter dans le corps -exec de find. de toute autre façon, vous suggérez? – JohnG

+0

Eh bien, cela dépend de ce que la commande est, et comment il fonctionnera uniquement sur le nom de fichier de base (surtout sans savoir où se trouve le fichier est le fichier réel). Si la commande peut accepter plusieurs noms de fichiers en tant que paramètres, vous pouvez par exemple rediriger la sortie de 'sed' vers' xargs other_command'. Si vous avez vraiment besoin d'invoquer la commande séparément pour chaque nom (pourquoi?) Alors la méthode d'Ignacio peut être meilleure, bien que vous puissiez sauvegarder un appel de shell par nom en démarrant la commande depuis le shell parent avec 'while read fname; faire une boucle après le 'sed'. –

8

Voici ce que vous cherchez:

find . -name "*.csv" -exec sh -c 'echo $(basename "$1")' sh {} \; 
+0

Je n'obtiens pas le point avec '$ 1' et le second' sh'. Pourquoi ne pas utiliser 'find. -name "* .csv" -exec sh -c 'echo $ (nom de base "$ 0")' {} \; '. Cela fonctionne parfaitement pour moi. – Tik0

+1

@ Tik0 Le point est la cohérence. Utiliser $ 0 fonctionnerait en effet ici mais en le faisant, il rompt la convention de $ 0 signifiant le nom du processus en cours d'exécution. Top ou ps signalerait, par exemple, des noms de commandes impairs. Des structures plus complexes comme une boucle for échoueraient. – jlliagre

+0

ah d'accord, donc le second 'sh' est juste un espace réservé pour garder la convention que le programme appelé est' sh' (c'est-à-dire le premier). – Tik0

Questions connexes