For each en bash
Il arrive souvent de devoir appliquer une commande bash à tout une liste de fichiers. Pour trouver des fichiers en particulier, la commande find fait très bien son travail. Mais pour appliquer une commande à chaque fichier trouvé, il faut utiliser exec ou xargs avec leurs syntaxes bizarres et tout un tas de détails à ne pas oublier sous peine d’erreur. Une boucle for each est une très bonne alternative, surtout quand on a l’habitude d’itérer en Python.
for f in $(find /home/moi -iname "*.jpg"); do echo $(readlink -f $f); done
En détails:
$() permet d’éxécuter en premier la commande entre parenthèses et de récupérer sa sortie.
readlink -f permet de transformer un chemin relatif en chemin absolu.
find /home/moi -iname "*.jpg" liste tous les fichiers qui finissent par .jpg dans le dossier courrant, sans tenir compte de la casse.
A noter que sur certains systèmes de fichiers (notamment issus du monde Microsoft), vous devrez utiliser l’option -noleaf sur find pour qu’il trouve tous les fichiers que vous cherchez.
for f in $(find /home/moi -iname "*.jpg"); do
echo $(readlink -f $f);
done
Peut donc se lire:
Pour chaque fichier du dossier
/home/moidont le nom finit par.jpg(en majuscule ou minuscule), afficher son chemin absolu.
On peut d’ailleurs l’écrire en une ligne en jouant sur les points virgules:
for f in $(find /home/moi -iname "*.jpg"); do echo $(readlink -f $f); done
EDIT suite à commentaires:
Si vous savez qu’il y a des espaces dans les chemins de fichiers, il vous faudra changer le séparateur de termes:
OLDIFS=$IFS # sauvegarde du séparateur par défaut (qui correspond à "tout espace") IFS=$'\n' # le séparateur est maintenant le saut de ligne for f in $(find /home/moi -iname "*.jpg"); do echo $(readlink -f $f); done IFS=$OLDIF # restauration du séparateur par défaut
Articles similaires:




Si les fichiers comportent des espaces dans leur nom, cette commande ne fonctionnera pas.
Plus d’info ici :
http://www.cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html
a+
C’est exacte, je vais modifier l’article pour y pallier.
Bonjour,
Deux petites remarques concernant l’exemple pris :
- À partir du moment où tu donne un chemin absolu à la commande find, le chemin en sortie (sauf demande explicite), sera toujours un chemin absolu.
- La commande “echo” dans “echo $(readlink -f $f)” est inutile, la commande “readlink” en elle même renvoie son résultat sur la sortie standard (l’écran).
Puis concernant la commande “find”, je ne vois pas ce qu’il y a de plus compliqué par rapport à la lourdeur de ta boucle “for… do… done” à mettre juste (espace dans le nom des fichiers compris):
find /home/toi -iname “*.jpg” -exec readlink -f {} \;
Bonne fin de week-end.
JP.
@zipe31 pour répondre à la dernière remarque: rajoutez awk dans la commande…
@sam Désolé mais je ne vois pas ce que vient faire awk là-dedans ;-\
Salut,
il faut faire attention dans le cas de scripts portable : les sous commandes shell avec `$(foo)’ ne sont pas toujours gere.
Il faut utiliser les back quotes a la place.
Sinon l’article est sympas : bravo. Je n’avais jamais ecrit IFS de cette maniere. J’ai plutot l’habitude de l’ecrire directement avec le saut de ligne en explicite :
IFS=’
‘