Que signifie “{} \;” dans la commande de recherche?


38

Parfois, je vois la commande suivante:

find . -name  * -exec ls -a {} \;

On m'a demandé d'exécuter ceci.

Que {} \;signifie ici?


2
-name *est redondant.
Kevin

3
Consultez également expliquehell pour d'autres types de questions comme celle-ci. Voici le résultat de votre commande. .
Glutanimate

10
-name *est pire que redondant. Parce que le *n'est pas entre guillemets, le shell le développe pour former la liste des noms de fichiers du dossier en cours, les espaces étant traités de manière incorrecte, ce qui entraîne des résultats inattendus ou un message d'erreur. Un point supplémentaire finda de nombreuses fonctions, l’une d’eux étant de lister les fichiers; cela évite d'avoir à utiliser -exec. Par exemple, vous pouvez utiliser find . -printou find . -ls. Enfin, il y a deux façons d'échapper à la demi-virgule: soit comme vous avez fait avec la barre oblique inverse, \;ou en citant: ';'. Utilisez celui avec lequel vous vous sentez le plus à l'aise.
Paddy Landau

Réponses:


49

Si vous exécutez findavec exec, {}étend le nom de fichier de chaque fichier ou répertoire trouvé avec find(pour que lsdans votre exemple, chaque nom de fichier trouvé soit considéré comme un argument - notez qu'il appelle lsou toute autre commande spécifiée une fois pour chaque fichier trouvé).

Le point-virgule ;met fin à la commande exécutée par exec. Il doit être échappé avec \pour que le shell dans lequel vous courez findne le traite pas comme son propre caractère spécial, mais le transmette à find.

Voir cet article pour plus de détails.


En outre, findfournit une optimisation avec exec cmd {} +- lorsque exécuté comme cela, findajoute les fichiers trouvés à la fin de la commande plutôt que de les invoquer une fois par fichier (pour que la commande ne soit exécutée qu'une fois, si possible).

La différence de comportement (sinon d'efficacité) est facilement perceptible si elle est exécutée avec ls, par exemple

find ~ -iname '*.jpg' -exec ls {} \;
# vs
find ~ -iname '*.jpg' -exec ls {} +

En supposant que vous ayez des jpgfichiers (avec des chemins suffisamment courts ), le résultat est une ligne par fichier dans le premier cas et un lscomportement standard d'affichage des fichiers en colonnes pour ce dernier.


1
Je pense qu'il serait avantageux pour vous de contraster \;avec +.
Kevin

Comment diffère-t-il find . -name * | ls -a -?
András Hummer

@DrH L'important n'est pas de laisser le shell développer le caractère générique, mais plutôt de lui transmettre l'expression find. De plus, la sortie de lsdans ce cas ne dépend apparemment pas de l'entrée - peu importe le filtre que j'utilise find, lsaffiche simplement le contenu du répertoire de travail et c'est tout. Consultez par exemple find ~ -iname '*.jpg' -exec ls -a {} \;vs find ~ -iname '*.jpg' | ls -a.
moon.musick

@DrH ou même echo 'foo' | ls -a.
moon.musick

@ moon.musick, je pense que vous avez manqué l'important -dans votre ls -a -commande lorsque vous testez ce que @ dr-h a demandé.
Daniel Llewellyn

21

Depuis la page de manuel de la findcommandeIcône de page de manuel :

-exec command ;
              Execute  command;  true if 0 status is returned.  All following arguments to find are taken to be arguments to
              the command until an argument consisting of `;' is encountered.  The string `{}' is replaced  by  the  current
              file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it
              is alone, as in some versions of find.  Both of these constructions might need to be escaped (with a  `\')  or
              quoted  to  protect them from expansion by the shell.

Alors voici l'explication:

{}signifie "la sortie de find". Comme dans "tout ce qui est findtrouvé". findrenvoie le chemin du fichier que vous recherchez, non? Alors le {}remplace; c'est un espace réservé pour chaque fichier que la findcommande localise (pris à partir d' ici ).

La \;partie dit essentiellement find"d'accord, j'ai fini avec la commande que je voulais exécuter".

Exemple:

Disons que je suis dans un répertoire plein de .txtfichiers. Je cours ensuite:

find . -name  '*.txt' -exec cat {} \;

La première partie, find . -name *.txtrenvoie la liste des .txtfichiers. La deuxième partie -exec cat {} \;exécutera la catcommande pour chaque fichier trouvé par find, etc. cat file1.txt, cat file2.txtetc.


4
La partie *.txtdoit être citée comme '*.txt'. En effet, s’il existe des .txtfichiers dans le dossier actuel, le shell le développera et vous obtiendrez des résultats incorrects ou un message d’erreur. find -name '*.txt' -exec cat {} \;
Paddy Landau

@Alaa Ali très bien expliqué
pushya
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.