Je me trouve constamment à la recherche de la syntaxe de
find . -name "FILENAME" -exec rm {} \;
principalement parce que je ne vois pas comment fonctionne exactement la -exec
pièce. Quelle est la signification des accolades, de la barre oblique inverse et du point-virgule? Existe-t-il d'autres cas d'utilisation de cette syntaxe?
man
page POSIX se lit comme suit: Un nom_utilitaire ou un argument ne contenant que les deux caractères "{}" doit être remplacé par le chemin actuel , ce qui me semble suffisant. De plus, il a un exemple avec-exec rm {} \;
, tout comme dans votre question. À l'époque, il n'existait guère d'autres ressources que le "grand mur gris", des livres deman
pages imprimées (le papier coûtait moins cher que le stockage). Donc, je sais que cela suffit pour quelqu'un de nouveau sur le sujet. Votre dernière question est cependant juste de poser ici. Malheureusement, ni @Kusalananda ni moi-même n’avons une réponse à cela.xargs
soit parfois pratique, vousfind
pouvez transmettre plusieurs arguments de chemin pour commander sans lui.-exec command... {} +
(avec+
au lieu de\;
) passe autant de cheminscommand...
que nécessaire (chaque système d’exploitation a sa propre limite quant à la longueur d’une ligne de commande). Et commexargs
, la+
forme de mots terminéefind
par »-exec
l'action sera également exécutécommand...
plusieurs fois dans les rares cas où il y a trop de chemins pour se loger dans la limite.Réponses:
Cette réponse se présente dans les parties suivantes:
-exec
-exec
en combinaison avecsh -c
-exec ... {} +
-execdir
Utilisation basique de
-exec
L'
-exec
option prend un utilitaire externe avec des arguments facultatifs comme arguments et l'exécute.Si la chaîne
{}
est présente n'importe où dans la commande donnée, chaque instance sera remplacée par le chemin d'accès en cours de traitement (par exemple./some/path/FILENAME
). Dans la plupart des coquillages, il{}
n'est pas nécessaire de citer les deux caractères .La commande doit être terminée avec un
;
forfind
pour savoir où elle se termine (car il peut y avoir d'autres options par la suite). Pour protéger le;
shell, il doit être cité comme\;
ou';'
, sinon le shell le verra comme la fin de lafind
commande.Exemple (la
\
fin des deux premières lignes ne concerne que les continuations de lignes):Ceci trouvera tous les fichiers normaux (
-type f
) dont les noms correspondent au modèle*.txt
dans ou sous le répertoire actuel. Il vérifiera ensuite si la chaînehello
apparaît dans l'un des fichiers trouvés à l'aide degrep -q
(ce qui ne produit aucune sortie, mais uniquement un état de sortie). Pour les fichiers contenant la chaîne,cat
sera exécuté pour afficher le contenu du fichier sur le terminal.Chacun
-exec
agit également comme un "test" sur les noms de chemins trouvés parfind
, tout comme-type
et le-name
fait. Si la commande renvoie un état de sortie nul (signifiant "succès"), la partie suivante de lafind
commande est considérée, sinon lafind
commande continue avec le chemin suivant. Ceci est utilisé dans l'exemple ci-dessus pour rechercher les fichiers contenant la chaînehello
, mais pour ignorer tous les autres fichiers.L'exemple ci-dessus illustre les deux cas d'utilisation les plus courants de
-exec
:find
commande).Utilisation
-exec
en combinaison avecsh -c
La commande
-exec
pouvant être exécutée est limitée à un utilitaire externe avec des arguments facultatifs. Utiliser directement les fonctions intégrées au shell, les fonctions, les conditions, les pipelines, les redirections, etc.-exec
n'est pas possible, à moins d'être enveloppé dans un environnement similaire à unsh -c
shell enfant.Si des
bash
fonctionnalités sont requises, utilisezbash -c
à la place desh -c
.sh -c
s’exécute/bin/sh
avec un script donné sur la ligne de commande, suivi d’arguments facultatifs en ligne de commande pour ce script.Un exemple simple d'utilisation
sh -c
par lui-même, sansfind
:Cela passe deux arguments au script shell enfant:
La ficelle
sh
. Cela sera disponible comme$0
dans le script, et si le shell interne génère un message d'erreur, il le préfixera avec cette chaîne.L'argument
apples
est disponible comme$1
dans le script, et s'il y avait eu plus d'arguments, ceux-ci auraient été disponibles comme$2
,$3
etc. Ils seraient également disponibles dans la liste"$@"
(sauf ceux$0
qui ne feraient pas partie de"$@"
).Ceci est utile en combinaison avec
-exec
car cela nous permet de faire des scripts arbitrairement complexes qui agissent sur les noms de chemins trouvés parfind
.Exemple: Recherchez tous les fichiers normaux portant un suffixe de nom de fichier donné et remplacez ce suffixe par un autre suffixe, les suffixes étant conservés dans des variables:
Dans le script interne,
$1
serait la chaînetext
,$2
serait la chaînetxt
et$3
serait tout chemin que cheminfind
a trouvé pour nous. Le paramètre expansion${3%.$1}
prendrait le chemin et en supprimait le suffixe.text
.Ou en utilisant
dirname
/basename
:ou, avec des variables ajoutées dans le script interne:
Notez que dans cette dernière variante, les variables
from
etto
dans le shell enfant sont distinctes des variables portant le même nom dans le script externe.Ce qui précède est la manière correcte d’appeler un script complexe arbitraire
-exec
avecfind
. Utiliserfind
en boucle commeest sujet aux erreurs et inélégant (opinion personnelle). Il divise les noms de fichiers sur des espaces, appelle la suppression du nom de fichier et oblige également le shell à développer le résultat complet
find
avant même d'exécuter la première itération de la boucle.Voir également:
En utilisant
-exec ... {} +
Le
;
à la fin peut être remplacé par+
. Ceci afind
pour effet d'exécuter la commande donnée avec autant d'arguments (noms de chemins d'accès trouvés) que possible plutôt qu'une fois pour chaque chemin d'accès trouvé. La chaîne{}
doit apparaître juste avant le+
pour que cela fonctionne .Ici,
find
collectera les noms de chemin résultants et exécuteracat
le plus grand nombre possible à la fois.De même ici,
mv
sera exécuté aussi peu de fois que possible. Ce dernier exemple nécessite GNUmv
de coreutils (qui supporte l’-t
option).Utiliser
-exec sh -c ... {} +
est également un moyen efficace de parcourir un ensemble de chemins avec un script arbitrairement complexe.Les bases sont les mêmes que lors de l'utilisation
-exec sh -c ... {} ';'
, mais le script nécessite maintenant une liste d'arguments beaucoup plus longue. Ceux-ci peuvent être bouclés en boucle"$@"
dans le script.Notre exemple de la dernière section qui modifie les suffixes de nom de fichier:
En utilisant
-execdir
Il existe également
-execdir
(mis en œuvre par la plupart desfind
variantes, mais pas une option standard).Cela fonctionne
-exec
à la différence que la commande shell donnée est exécutée avec le répertoire du chemin trouvé en tant que répertoire de travail actuel et qu'il{}
contiendra le nom de base du chemin trouvé sans son chemin (mais GNUfind
préfixera toujours le nom de base avec./
, alors que BSDfind
ne fera pas ça).Exemple:
Cela déplacera chaque
*.txt
fichier- trouvé dans undone-texts
sous - répertoire préexistant dans le même répertoire que celui où le fichier a été trouvé . Le fichier sera également renommé en y ajoutant le suffixe.done
.Ce serait un peu plus délicat à faire
-exec
car il faudrait extraire le nom de base du fichier trouvé{}
pour former le nouveau nom du fichier. Nous avons également besoin du nom de répertoire de{}
pour localiser ledone-texts
répertoire correctement.Avec
-execdir
, certaines choses comme celles-ci deviennent plus faciles.L'opération correspondante utilisant à la
-exec
place de-execdir
devrait utiliser un shell enfant:ou,
la source
-exec
prend un programme et des arguments et l'exécute; Certaines commandes shell ne comprennent qu'un programme et des arguments, mais d'autres non. Une commande shell peut inclure la redirection et la tuyauterie;-exec
ne peut pas (bien que le toutfind
puisse être redirigé). Une commande shell peut utiliser; && if
etc;-exec
ne peut pas, bien que-a -o
peut en faire. Une commande shell peut être un alias ou une fonction shell, ou intégrée;-exec
ne peux pas. Une commande shell peut développer des vars;-exec
ne peut pas (bien que la coque externe qui exécute lafind
boîte). Une commande shell peut se substituer$(command)
différemment à chaque fois;-exec
ne peux pas. ...-exec
ne peut pas - bien qu'ellefind
puisse parcourir les fichiers de la même manière que la plupart des globs, ce qui est rarement voulu.sh
elle-même, ce qui est tout à fait capable de faire tout celafind -exec cmd arg \;
n'appelle pas un shell pour interpréter une ligne de commande, cela ne s'exécute pasexeclp("cmd", "arg")
directementexeclp("sh", "-c", "cmd arg")
(pour lequel le shell finirait par faire l'équivalent deexeclp("cmd", "arg")
ifcmd
n'était pas intégré).find
arguments après-exec
et jusqu'à;
ou+
composent la commande à exécuter avec ses arguments, chaque instance d'un{}
argument étant remplacée par le fichier en cours (avec;
) et,{}
en dernier lieu,+
par une liste de fichiers. comme arguments séparés (dans le{} +
cas). IOW-exec
prend plusieurs arguments, terminés par un;
ou{}
+
.