La réponse de muru est appropriée et bien adaptée aux cas où nous voulons imprimer quelque chose si un fichier est trouvé. Pour le cas général où nous voulons exécuter une commande externe, comme echo
, nous pourrions utiliser -exec
flag.
$ find . -name 'xac' -exec echo "I found " {} \; -quit
I found ./xac
La {}
partie transmet le nom de fichier à la commande entre -exec
et \;
comme arguments. Notez ce qui \
précède ;
- il empêche le shell de l'interpréter de manière erronée ; dans le shell fermant le point-virgule signifie la fin de la commande, mais lorsqu'il est échappé avec une barre oblique, le shell le traitera comme du texte littéral à passer à la find
commande et pour trouver la commande, il servira -exec
d'argument du drapeau de fermeture .
Pour construire des conditionnelles de ce if found do this; else do that
type, nous pourrions utiliser la sous-station de commande $()
et la test
commande (aka [
):
$ [ "x$(find . -name 'noexist' -print -quit)" != "x" ] && echo "found" || echo "not found"
not found
$ [ "x$(find . -name 'xac' -print -quit)" != "x" ] && echo "found" || echo "not found"
found
Répondre au commentaire de Dan
Dan dans les commentaires demandait:
L'écho "J'ai trouvé {}" ne serait-il pas meilleur que l'écho "J'ai trouvé" {}? Peut-être que pour l'écho, c'est bien, mais si quelqu'un copie la commande et remplace l'écho par une autre commande, il peut avoir un problème
Comprenons d'abord le problème. Habituellement, dans les coquilles, il existe un concept de séparation des mots, ce qui signifie que les variables non cotées et les paramètres de position seront développés et traités comme des éléments distincts. Par exemple, si vous avez variables var
et il contient du hello world
texte, quand vous faites touch $var
le shell décomposer en deux éléments distincts hello
et world
et touch
comprendra que si vous essayez de créer 2 fichiers séparés; si vous le faites touch "$var"
, le shell sera traité hello world
comme une seule unité et touch
ne créera qu'un seul fichier. Il est important de comprendre que cela se produit uniquement en raison du fonctionnement des obus.
En revanche, find
ne souffre pas d'un tel comportement, car les commandes sont traitées par find
lui-même et exécutées par execvp()
appel système, donc aucun shell n'est impliqué. Bien que les accolades aient une signification particulière dans les coquilles, car elles apparaissent au milieu de la find
commande et non au début, elles n'ont aucune signification particulière à coquiller dans ce cas. Voici un exemple. Créons quelques noms de fichiers difficiles et essayons de les passer comme argument à stat
commander.
$ touch with$'\t'tab.txt with$' 'space.txt with$'\n'newline.txt
$ find -type f -exec stat -c "%F" {} \; -print
regular empty file
./with?newline.txt
regular empty file
./with space.txt
regular empty file
./with?tab.txt
Comme vous pouvez le voir, stat
reçoit parfaitement les noms de fichiers difficiles find
, ce qui est l'une des principales raisons pour lesquelles il est recommandé pour une utilisation dans des scripts portables, et particulièrement utile lorsque vous parcourez l'arborescence de répertoires et que vous voulez faire quelque chose avec des noms de fichiers qui pourraient potentiellement avoir caractères spéciaux en eux. Par conséquent, il n'est pas nécessaire de citer des accolades pour les commandes exécutées dans find
.
C'est une autre histoire lorsque Shell s'implique. Parfois, vous devez utiliser un shell pour traiter le nom de fichier. Dans ce cas, la citation importera en effet, mais il est important de réaliser que ce n'est pas le problème de la recherche - c'est le shell qui fait le fractionnement des mots.
$ find -type f -exec bash -c "stat {}" sh \;
stat: cannot stat './with': No such file or directory
sh: line 1: newline.txt: command not found
stat: cannot stat './with': No such file or directory
stat: cannot stat 'space.txt': No such file or directory
stat: cannot stat './with': No such file or directory
stat: cannot stat 'tab.txt': No such file or directory
Donc, lorsque nous citons dans shell , cela fonctionnera. Mais encore une fois, c'est important pour shell, non find
.
$ find -type f -exec bash -c "stat -c '%F' '{}'" sh \;
regular empty file
regular empty file
regular empty file
/some/path
indique où commencer à chercher, mais rien ne lui dit quoi chercher. Même chose dans votre réponse liée. Ce qui fonctionne pour moi, c'estfind /some/path -name xac -print0 -quit | grep -qz . && echo found
. Ai-je oublié quelque chose?