Je veux que mon bash imprime 'trouvé' seulement si quelque chose est trouvé, en utilisant la commande find. Mais utiliser && n’aide en rien: même si rien n’est trouvé, je reçois l’impression "trouvé". Exemple:
$ pwd
/data/data/com.termux/files/home/test/test1/test4
$ ls
xaa xab
$ find . -name xac && echo 'found'
found
$ find . -name xaa && echo 'found'
./xaa
found
Vous pouvez créer find
lui-même imprimer found
:
find . -name xac -printf "found\n" -quit
Le -quit
fera find
quitter après le premier match , donc found
n'est imprimé qu'une fois au maximum.
Sur un thread similaire sous Unix et Linux ( (make find fail si rien n'a été trouvé ), j'ai utilisé grep -qz
pour renvoyer un statut de sortie non nul si find
ne trouvait rien:
find /some/path -print0 -quit | grep -qz .
Ce que vous pouvez utiliser pour construire des commandes composées en utilisant &&
ou if
:
find /some/path -print0 -quit | grep -qz . && echo found
réponse de mur est approprié et bien adapté aux cas où nous voulons imprimer quelque chose si un fichier est trouvé. Dans le cas général où nous souhaitons exécuter une commande externe, telle que echo
, nous pourrions utiliser le drapeau -exec
.
$ find . -name 'xac' -exec echo "I found " {} \; -quit
I found ./xac
La partie {}
transmet le nom de fichier à la commande entre -exec
et \;
en tant qu'arguments. Notez que \
avant ;
- il empêche Shell de l’interpréter de manière erronée ; dans le point-virgule de fermeture de Shell, signifiant la fin de la commande, mais Shell le traite comme un texte à transmettre à la commande find
et pour trouver une commande, elle sert de fermeture aux arguments de -exec
flag.
Pour construire des conditions de type if found do this; else do that
, nous pourrions utiliser les commandes Substance $()
et test
(alias [
):
$ [ "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
Adressant le commentaire de Dan
Dan dans le commentaires a demandé:
L'écho "j'ai trouvé {}" ne serait-il pas meilleur que l'écho "j'ai trouvé" {}? Peut-être que pour echo ça va, mais si quelqu'un copie la commande et remplace echo par une autre commande, il peut avoir un problème
Comprenons d'abord le problème. Généralement, dans les shells, il existe un concept de fractionnement de Word, ce qui signifie que les variables non entre guillemets et les paramètres de position seront développés et traités séparément. Par exemple, si vous avez la variable var
et qu'elle contient hello world
text, lorsque vous faites touch $var
, le shell le décomposera en deux éléments distincts: hello
et world
et touch
comprendront que vous essayez créer 2 fichiers séparés; si vous faites touch "$var"
, alors Shell traitera hello world
comme une 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 coquilles.
En revanche, find
ne souffre pas d'un tel comportement, car les commandes sont traitées par find
et exécutées par execvp()
appel système. Il n'y a donc pas de shell impliqué. Bien que les accolades aient une signification particulière dans les shells, car elles apparaissent au milieu de la commande find
et non au début, elles n’ont aucune signification particulière pour Shell dans ce cas. Voici un exemple. Créons quelques noms de fichiers difficiles et essayons de les passer en tant qu'argument à la commande stat
.
$ 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 constater, stat
reçoit parfaitement les noms de fichiers difficiles avec find
, ce qui est l’une des principales raisons pour lesquelles il est recommandé de l’utiliser dans les scripts portables, et particulièrement utile lorsque vous parcourez une arborescence de répertoires et que vous souhaitez utiliser des noms de fichiers qui puissent potentiellement avoir des 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 quand Shell intervient. Parfois, vous devez utiliser un shell pour traiter le nom de fichier. Dans ce cas, la citation importera, mais il est important de réaliser que ce n’est pas le problème de la découverte: c’est le shell qui effectue le fractionnement de Word.
$ 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
Ainsi, lorsque nous citerons dans Shell , cela fonctionnera. Mais là encore, c’est important pour Shell et non pas find
.
$ find -type f -exec bash -c "stat -c '%F' '{}'" sh \;
regular empty file
regular empty file
regular empty file