find-exec une fonction shell sous Linux?
Est-il un moyen d'obtenir find
pour exécuter une fonction que j'définir dans le shell? Par exemple:
dosomething () {
echo "doing something with $1"
}
find . -exec dosomething {} \;
Le résultat est de:
find: dosomething: No such file or directory
Est-il un moyen d'obtenir find
's -exec
à voir dosomething
?
Vous devez vous connecter pour publier un commentaire.
Depuis que la shell sait comment faire pour exécuter les fonctions d'interpréteur de commandes, vous devez exécuter un shell pour exécuter une fonction. Vous avez également besoin de marquer votre fonction pour exporter avec
export -f
, sinon le shell interne est exécuté de ne pas hériter d'eux:$0
.{}
argument de trouver a dû être un mot distinct, mais apparemment pas.find . -exec bash -c 'dosomething "$0"' {} \;
il va gérer les espaces (et d'autres caractères bizarres) dans les noms de fichiers...'dosomething "{}"'
? (merci Adam)export -f
ne fonctionne que dans certaines versions de bash. Ce n'est pas posix, pas crossplatforn,/bin/sh
aurez une erreur avec elle$1
. Si le mini-script devient un peu plus compliqué, cela pourrait être très déroutant. Je propose d'utiliserexport -f dosomething; find . -exec bash -c 'dosomething "$1"' _ {} \;
à la place."$0"
dansbash -c 'dosomething "$0"' {}
ou"$1"
dansbash -c 'dosomething "$1"' _ {}
? Est-il un nom pour cette fonction? Que dois-je rechercher si je voulais plus d'informations?while read
a des problèmes lors de l'exécution de commandes avecssh
; stackoverflow.com/questions/13800225/...while read
pour une boucle for;for item in $(find . ); do some_function "${item}"; done
Ajouter des guillemets dans
{}
comme indiqué ci-dessous:Cela corrige toute erreur due à des caractères spéciaux retourné par
find
,par exemple les fichiers avec des parenthèses dans leur nom.
{}
. Cette pause pour un nom de fichier contenant des guillemets doubles.touch '"; rm -rf .; echo "I deleted all you files, haha
. Oups.La réponse ci-dessus est bien, mais il a un couple de pièges qui sont facilement surmontés:
Cette null est utilisé comme un délimiteur au lieu d'un saut de ligne, de sorte que les noms de fichiers avec des sauts de ligne va travailler. Il utilise également la
-r
drapeau qui désactive la barre oblique inverse s'échapper, sans elle, les barres obliques inverses dans les noms de fichiers ne fonctionne pas. Il efface égalementIFS
de sorte que le potentiel de fuite des espaces dans les noms ne sont pas jetés./bin/bash
mais ne fonctionne pas dans/bin/sh
. Ce qui est dommage.Ont l'appel du script lui-même, en passant chaque élément trouvé comme argument:
Lorsque vous exécutez le script en lui-même, il trouve ce que vous cherchez et appelle lui-même en passant chaque résultat de la recherche comme argument. Lorsque le script est exécuté avec un argument, il exécute les commandes sur l'argument, puis se ferme.
find: ‘myscript.sh’: No such file or directory
si on commence commebash myscript.sh
...Les résultats du traitement en vrac
Pour plus d'efficacité, beaucoup de gens utilisent
xargs
pour traiter les résultats en vrac, mais il est très dangereux. Parce qu'il y a une autre méthode introduit dansfind
qui exécute les résultats en vrac.Notez bien que cette méthode pourrait venir avec quelques mises en garde, comme par exemple, une exigence dans POSIX-
find
avoir{}
à la fin de la commande.find
va passer beaucoup de résultats en tant qu'arguments à un simple appel debash
et lafor
-boucle parcourt ces arguments, l'exécution de la fonctiondosomething
sur chacun de ceux-ci.La solution ci-dessus commence arguments à
$1
, qui est pourquoi il est_
(qui représente$0
).Les résultats de traitement un par un
De la même façon, je pense que l'on a accepté la réponse sommet devrait être corrigé pour être
Ce n'est pas seulement plus sain, parce que les arguments doivent toujours commencer à
$1
, mais aussi à l'aide de$0
pourrait conduire à un comportement inattendu si le nom de fichier renvoyé parfind
a une signification particulière pour le shell.Pour ceux d'entre vous à la recherche d'un bash de la fonction à exécuter une commande sur tous les fichiers dans le répertoire courant, j'ai compilé un de l'réponses ci-dessus:
Noter qu'il rompt avec les noms de fichier contenant des espaces (voir ci-dessous).
Comme un exemple, prenez cette fonction:
Dire que je voulais changer toutes les instances de bonjour tout le monde, dans tous les fichiers dans le répertoire courant. Je voudrais faire:
Être en sécurité avec tous les symboles dans les noms de fichiers, utilisation:
(mais vous avez besoin d'un
find
qui gère-print0
par exemple, GNUfind
).- Je trouver la façon la plus simple que de suivre, en répétant deux commandes simples ne
Il n'est pas possible à l'exécutable d'un fonction de cette façon.
Pour surmonter cela, vous pouvez placer votre fonction dans un script shell, et de l'appeler à partir d'
find
Maintenant l'utiliser en trouver des comme:
dosomething $1
=>dosomething "$1"
et commencer votre fichier correctement avecfind . -exec bash dosomething.sh {} \;
Mettre la fonction dans un fichier séparé et d'obtenir
find
pour l'exécuter.Fonctions d'interpréteur de commandes internes au shell qu'ils sont définis dans;
find
ne sera jamais en mesure de les voir.Pour la référence, je éviter ce scénario en utilisant:
Obtenir la Sortie de la trouver dans le script courant de fichiers et d'effectuer une itération sur la sortie que vous le désirez.
Je suis d'accord avec la réponse, mais je ne veux pas exposer la fonction à l'extérieur de mon fichier de script.
Pas directement, non. Trouver en cours d'exécution dans un processus distinct, pas dans votre coquille.
Créer un script shell qui fait le même travail que votre fonction et de trouver peut
-exec
que.Je voudrais éviter d'utiliser
-exec
tout à fait. Pourquoi ne pas utiliserxargs
?