trouver-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 "
}
find . -exec dosomething {} ;
Le résultat est:
find: dosomething: No such file or directory
y a-t-il un moyen d'obtenir find
's -exec
pour voir dosomething
?
12 réponses
puisque seul le shell sait exécuter des fonctions shell, vous devez exécuter un shell pour exécuter une fonction. Vous devez également marquer votre fonction pour l'exportation avec export -f
, sinon le tréfoncier ne les héritera pas:
export -f dosomething
find . -exec bash -c 'dosomething ""151900920""' {} \;
ajouter les guillemets {}
comme suit:
export -f dosomething
find . -exec bash -c 'dosomething "{}"' \;
ceci corrige toute erreur due aux caractères spéciaux retournés par find
,
par exemple les fichiers avec des parenthèses dans leur nom.
la réponse de Jak's ci-dessus est grande, mais a un couple d'écueils qui sont facilement surmontés:
find . -print0 | while IFS= read -r -d '' file; do dosomething "$file"; done
cela utilise null comme délimiteur au lieu d'un linefeed, donc les noms de fichiers avec linefeeds fonctionneront. Il utilise également le drapeau -r
qui désactive backslash échappant, sans lui backslash dans les noms de fichiers ne fonctionnera pas. Il efface également IFS
de sorte que les espaces blancs potentiels traînants dans les noms ne sont pas écartés.
fait que le script s'appelle lui-même, en passant chaque élément trouvé comme argument:
#!/bin/bash
if [ ! == "" ] ; then
echo "doing something with "
exit 0
fi
find . -exec "151900920" {} \;
exit 0
quand vous exécutez le script par lui-même, il trouve ce que vous cherchez et s'appelle lui-même passant chaque résultat de find comme argument. Quand le script est lancé avec un argument, il exécute les commandes sur l'argument et puis sort.
résultats du traitement en vrac
pour une efficacité accrue, beaucoup de gens utilisent xargs
pour traiter les résultats en vrac, mais il est très dangereux. En raison de cela, il y avait une méthode alternative introduite dans find
qui exécute les résultats en vrac.
noter cependant que cette méthode pourrait venir avec quelques mises en garde comme par exemple une exigence dans POSIX - find
d'avoir {}
à la fin de la commande.
export -f dosomething
find . -exec bash -c 'for f; do dosomething "$f"; done' _ {} +
find
transmettra de nombreux résultats comme arguments à un seul appel de bash
et la boucle for
itère à travers ces arguments, exécutant la fonction dosomething
sur chacun de ceux-ci.
la solution ci-dessus commence les arguments à , c'est pourquoi il y a un
_
(qui représente " 1519120920"
).
les résultats de Traitement un par un
de la même manière, je je pense que la réponse la plus acceptée devrait être corrigée pour être
export -f dosomething
find . -exec bash -c 'dosomething ""' _ {} \;
ce n'est pas seulement plus sain, car les arguments devraient toujours commencer par , mais aussi utiliser
" 1519120920 "
pourrait conduire à un comportement inattendu si le nom de fichier retourné par find
a une signification spéciale pour le shell.
pour ceux d'entre vous qui cherchent une fonction bash qui exécutera une commande donnée sur tous les fichiers du répertoire courant, j'en ai compilé une à partir des réponses ci-dessus:
toall(){
find . -type f | while read file; do "" "$file"; done
}
notez qu'il casse avec des noms de fichiers contenant des espaces (voir ci-dessous).
à titre d'exemple, prenez cette fonction:
world(){
sed -i 's_hello_world_g' ""
}
dire que je voulais changer toutes les instances de hello to world dans tous les fichiers dans le courant répertoire. Je ferais:
toall world
pour être sûr avec n'importe quel symbole dans les noms de fichiers, utilisez:
toall(){
find . -type f -print0 | while IFS= read -r -d '' file; do "" "$file"; done
}
(mais vous avez besoin d'un find
qui gère -print0
par exemple, GNU find
).
il n'est pas possible d'exécuter une fonction de cette façon.
pour surmonter cela, vous pouvez placer votre fonction dans un script shell et l'appeler de find
# dosomething.sh
dosomething () {
echo "doing something with "
}
dosomething
utilisez-le maintenant dans find as:
find . -exec dosomething.sh {} \;
place la fonction dans un fichier séparé et obtient find
pour l'exécuter.
les fonctions Shell sont internes au shell dans lequel elles sont définies; find
ne sera jamais capable de les voir.
je trouve la voie la plus facile comme suit, en répétant deux commandes en une seule do
func_one () {
echo "first thing with "
}
func_two () {
echo "second thing with "
}
find . -type f | while read file; do func_one $file; func_two $file; done
Pas directement, non. Find est exécuté dans un processus séparé, pas dans votre shell.
créez un script shell qui fait le même travail que votre fonction et trouvez -exec
cela.
je voudrais éviter d'utiliser -exec
tout à fait. Pourquoi ne pas utiliser xargs
?
find . -name <script/command you're searching for> | xargs bash -c