web-dev-qa-db-fra.com

Comment puis-je traiter les résultats de find dans un script bash?

J'essaie d'utiliser un tableau pour stocker une liste de noms de fichiers à l'aide de la commande find.

Pour une raison quelconque, le tableau ne fonctionne pas dans le bash utilisé par l'école, mon programme fonctionne cependant sur mon propre ordinateur portable.

Je me demandais donc s'il y avait une autre façon de le faire, voici ce que j'ai:

array = (`find . -name "*.txt"`)  #this will store all the .txt files into the array

Ensuite, je peux accéder aux éléments du tableau et faire des copies de tous les fichiers à l'aide de la commande cat.

Existe-t-il une autre façon de le faire sans utiliser de tableau?

57
Shellscriptbeginner

Vous pouvez utiliser quelque chose comme ça:

find . -name '*.txt' | while read line; do
    echo "Processing file '$line'"
done

Par exemple. faire une copie:

find . -name '*.txt' | while read line; do
    echo "Copying '$line' to /tmp"
    cp -- "$line" /tmp
done

HTH

110
Johannes Weiss

J'avais un problème avec la solution de Johannes Weiß, si je faisais juste un écho, cela fonctionnerait pour la liste complète des fichiers. Cependant, si j'essayais d'exécuter ffmpeg sur la ligne suivante, le script ne traiterait que le premier fichier rencontré. J'ai supposé des affaires drôles IFS en raison de la pipe mais je n'ai pas pu le comprendre et j'ai couru avec une boucle for à la place:

for i in $(find . -name '*.mov' ); 
do
    echo "$i"
done
20
starpause

Ne mettez pas de blancs autour du signe égal:

ar=($(find . -name "*.txt"))

Évitez les contre-coups, si possible, car ils sont obsolètes. Ils peuvent être facilement confondus avec l'apostrophie, en particulier dans les polices de caractères pauvres, et ils ne s'emboîtent pas si bien.

Dans la plupart des cas, vous serez mieux servi si vous parcourez un résultat de recherche directement avec -exec, -execdir, -ok ou -okdir.

Les boucles For et While sont difficiles à faire correctement en ce qui concerne les blancs dans les noms de fichiers ou les nouvelles lignes et les tabulations.

find ./ -name "*.txt" -exec grep {} ";"

Le {} n'a pas besoin de masquage. Vous verrez souvent une combinaison find/xargs qui démarre également un processus supplémentaire:

find ./ -name "*.txt" | xargs grep {} ";"
7
user unknown

Je pense que la starpause a la solution la plus propre, mais elle échoue quand il y a des espaces blancs dans les chemins. Ceci est corrigé en définissant IFS. La bonne réponse est donc:

IFS=$'\n'
for i in $(find . -name '*.mov' ); 
do
    echo "$i"
done
unset IFS

Vous désactivez IFS afin de réinitialiser le comportement d'IFS et pourquoi le $ est nécessaire dans IFS=$'\n', voir https://unix.stackexchange.com/questions/184863/what-is-the-meaning-of-ifs-n-in-bash-scripting

5
beruic
find . -name '*.txt' | while IFS= read -r FILE; do
    echo "Copying $FILE.."
    cp "$FILE" /destination
done
3
ghostdog74