[bash] bonne façon de faire une boucle sur un ensemble de fichiers contenu dans un dossier
35 réponses
Francois Lafont
Bonjour à tous,
Assez régulièrement, je suis amené à me faire des petits scripts bash
qui font une boucle sur une liste de fichiers contenus dans un dossier
(et dans ses sous-dossiers etc). La liste de fichiers, qui peut être
assez grande, est obtenue à l'aide de la commande find. Le but est de
faire un même petit traitement sur chacun des fichiers de cette liste
via une boucle (le traitement importe peu ici, ça peut être un
"renommage", un grep etc). La structure de mes petits scripts
ressemblent à ça du coup (c'est un exemple) :
#-------------------------------------
for fichier in $(find /le/dossier/ -type f -iname '*.tex')
do
echo Traitement de $fichier
# etc.
done
#-------------------------------------
Est-ce la bonne façon de procéder ? J'ai des doutes :
1) En effet, finalement le script revient à ça :
#-------------------------------------
for fichier in /le/dossier/f1.tex /le/dossier/f2.tex /le/dossier/f3.tex
do
echo Traitement de $fichier
# etc.
done
#-------------------------------------
Du coup, si la liste est très grande, ça me semble un peu maladroit
comme script et peut-être pas très performant. (Aucune certitude bien
sûr, c'est juste une intuition.)
2) Une autre chose qui me fait penser que ce n'est peut-être pas la
bonne façon de procéder, c'est le problème avec les noms de fichiers qui
contiennent un espace. Si find détecte un fichier qui s'appelle par
exemple "/le/dossier/sous dossier/toto.tex" alors, durant la boucle,
$fichier sera égal à la chaîne "/le/dossier/sous" puis à
"dossier/toto.tex" mais jamais à "/le/dossier/sous dossier/toto.tex".
Bref, quelle est la bonne façon de faire ce genre de boucle ?
Merci d'avance pour votre aide.
Le 22-05-2011, Francois Lafont nous expliquait dans fr.comp.os.linux.configuration :
Bonjour à tous,
Bonjour,
#------------------------------------- for fichier in $(find /le/dossier/ -type f -iname '*.tex') do echo Traitement de $fichier # etc. done #-------------------------------------
Est-ce la bonne façon de procéder ? J'ai des doutes :
Je ne suis pas spécialiste mais je pense que tu peux jetter un oeil à l'option -exec de find.
D'autres options de manipulation de fichier existent également (-delete par ex).
man find -- Doug - Linux user #307925 - Slackware64 roulaize ;-) http://www.dougwise.org http://usenet-fr.dougwise.org http://news.dougwise.org
Le 22-05-2011, Francois Lafont nous expliquait dans
fr.comp.os.linux.configuration :
Bonjour à tous,
Bonjour,
#-------------------------------------
for fichier in $(find /le/dossier/ -type f -iname '*.tex')
do
echo Traitement de $fichier
# etc.
done
#-------------------------------------
Est-ce la bonne façon de procéder ? J'ai des doutes :
Je ne suis pas spécialiste mais je pense que tu peux jetter un oeil à
l'option -exec de find.
D'autres options de manipulation de fichier existent également
(-delete par ex).
man find
--
Doug - Linux user #307925 - Slackware64 roulaize ;-)
http://www.dougwise.org
http://usenet-fr.dougwise.org
http://news.dougwise.org
Le 22-05-2011, Francois Lafont nous expliquait dans fr.comp.os.linux.configuration :
Bonjour à tous,
Bonjour,
#------------------------------------- for fichier in $(find /le/dossier/ -type f -iname '*.tex') do echo Traitement de $fichier # etc. done #-------------------------------------
Est-ce la bonne façon de procéder ? J'ai des doutes :
Je ne suis pas spécialiste mais je pense que tu peux jetter un oeil à l'option -exec de find.
D'autres options de manipulation de fichier existent également (-delete par ex).
man find -- Doug - Linux user #307925 - Slackware64 roulaize ;-) http://www.dougwise.org http://usenet-fr.dougwise.org http://news.dougwise.org
Aéris
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Le 22/05/2011 18:27, Francois Lafont a écrit :
for fichier in $(find /le/dossier/ -type f -iname '*.tex') do echo Traitement de $fichier # etc. done
find /le/dossier/ -type f -iname '*.tex' | while read FILE; do echo "${FILE}" done
- -- Aeris -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
Je ne suis pas spécialiste mais je pense que tu peux jetter un oeil à l'option -exec de find.
Oui, je connais l'option -exec mais le souci c'est que même si le traitement sur chaque fichier est assez basique en général, il m'est souvent difficile de le faire tenir sur une seule ligne. Du coup, j'avais pensé à faire un truc dans ce genre :
function f(){ echo Traitement de $1 # etc. }
find /le/dossier/ -type f -exec f {} ;
Mais dans l'option -exec, la fonction f semble totalement inconnue et le code ne fonctionne pas.
-- François Lafont
Le 22/05/2011 18:34, Doug713705 a écrit :
Je ne suis pas spécialiste mais je pense que tu peux jetter un oeil à
l'option -exec de find.
Oui, je connais l'option -exec mais le souci c'est que même si le
traitement sur chaque fichier est assez basique en général, il m'est
souvent difficile de le faire tenir sur une seule ligne. Du coup,
j'avais pensé à faire un truc dans ce genre :
function f(){
echo Traitement de $1
# etc.
}
find /le/dossier/ -type f -exec f {} ;
Mais dans l'option -exec, la fonction f semble totalement inconnue et le
code ne fonctionne pas.
Je ne suis pas spécialiste mais je pense que tu peux jetter un oeil à l'option -exec de find.
Oui, je connais l'option -exec mais le souci c'est que même si le traitement sur chaque fichier est assez basique en général, il m'est souvent difficile de le faire tenir sur une seule ligne. Du coup, j'avais pensé à faire un truc dans ce genre :
function f(){ echo Traitement de $1 # etc. }
find /le/dossier/ -type f -exec f {} ;
Mais dans l'option -exec, la fonction f semble totalement inconnue et le code ne fonctionne pas.
-- François Lafont
Francois Lafont
Le 22/05/2011 18:35, Aéris a écrit :
find /le/dossier/ -type f -iname '*.tex' | while read FILE; do echo "${FILE}" done
Merci bien Aéris, ça m'a l'air parfait. J'aimerais simplement comprendre la différence entre ${FILE} et $FILE, je ne vois pas trop.
-- François Lafont
Le 22/05/2011 18:35, Aéris a écrit :
find /le/dossier/ -type f -iname '*.tex' | while read FILE; do
echo "${FILE}"
done
Merci bien Aéris, ça m'a l'air parfait. J'aimerais simplement comprendre
la différence entre ${FILE} et $FILE, je ne vois pas trop.
Mais dans l'option -exec, la fonction f semble totalement inconnue et le code ne fonctionne pas.
Faut exporter la fonction, et lancer un shell dans exec :
export func find /dossier-type f -exec sh -c 'func $1' _ {} ;
-- XAv In your pomp and all your glory you're a poorer man than me, as you lick the boots of death born out of fear. (Jethro Tull)
Nicolas George
Francois Lafont , dans le message <4dd9395e$0$18114$, a écrit :
Assez régulièrement, je suis amené à me faire des petits scripts bash qui font une boucle sur une liste de fichiers contenus dans un dossier (et dans ses sous-dossiers etc). La liste de fichiers, qui peut être assez grande, est obtenue à l'aide de la commande find.
Jette bash en faveur de zsh :
setopt extendedglob for f in **/*.(#i)tex; { ... frobincate $f }
Francois Lafont , dans le message
<4dd9395e$0$18114$426a74cc@news.free.fr>, a écrit :
Assez régulièrement, je suis amené à me faire des petits scripts bash
qui font une boucle sur une liste de fichiers contenus dans un dossier
(et dans ses sous-dossiers etc). La liste de fichiers, qui peut être
assez grande, est obtenue à l'aide de la commande find.
Jette bash en faveur de zsh :
setopt extendedglob
for f in **/*.(#i)tex; {
... frobincate $f
}
Francois Lafont , dans le message <4dd9395e$0$18114$, a écrit :
Assez régulièrement, je suis amené à me faire des petits scripts bash qui font une boucle sur une liste de fichiers contenus dans un dossier (et dans ses sous-dossiers etc). La liste de fichiers, qui peut être assez grande, est obtenue à l'aide de la commande find.
Jette bash en faveur de zsh :
setopt extendedglob for f in **/*.(#i)tex; { ... frobincate $f }
Aéris
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Le 22/05/2011 18:55, Francois Lafont a écrit :
Merci bien Aéris, ça m'a l'air parfait. J'aimerais simplement comprendre la différence entre ${FILE} et $FILE, je ne vois pas trop.
Y'en a pas vraiment. {} te permet juste de faire des trucs plus complexes, du style BIDULE=truc echo "${BIDULE}muche" Sans les accolades, ça serait impossible.
Et j'ai pris l'habitude de les mettre partout du coup =)
- -- Aeris -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
Merci bien Aéris, ça m'a l'air parfait. J'aimerais simplement comprendre
la différence entre ${FILE} et $FILE, je ne vois pas trop.
Y'en a pas vraiment.
{} te permet juste de faire des trucs plus complexes, du style
BIDULE=truc
echo "${BIDULE}muche"
Sans les accolades, ça serait impossible.
Et j'ai pris l'habitude de les mettre partout du coup =)
- --
Aeris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
Merci bien Aéris, ça m'a l'air parfait. J'aimerais simplement comprendre la différence entre ${FILE} et $FILE, je ne vois pas trop.
Y'en a pas vraiment. {} te permet juste de faire des trucs plus complexes, du style BIDULE=truc echo "${BIDULE}muche" Sans les accolades, ça serait impossible.
Et j'ai pris l'habitude de les mettre partout du coup =)
- -- Aeris -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
Aéris , dans le message <4dd9436b$0$13039$, a écrit :
BIDULE=truc echo "${BIDULE}muche" Sans les accolades, ça serait impossible.
echo "$BIDULE""muche"
Francois Lafont
Le 22/05/2011 19:07, Xavier a écrit :
find /le/dossier/ -type f -exec f {} ;
Mais dans l'option -exec, la fonction f semble totalement inconnue et le code ne fonctionne pas.
Faut exporter la fonction, et lancer un shell dans exec :
Ok, mais j'imagine pour le coup que les performances s'en trouvent amoindries.
export func find /dossier-type f -exec sh -c 'func $1' _ {} ;
Je crois qu'Aéris a parfaitement résolu mon problème, ceci étant, par curiosité, j'ai essayé de faire fonctionner cette idée et je n'y suis pas arrivé. J'ai fait ça :
function f(){ echo Traitement de $1 } export f find /le/dossier -type f -exec sh -c 'f $1' _ {} ;
Je ne comprends pas trop le «-c 'f $1'» et le underscore qui vient juste après. J'ai bien tenté un "man sh", mais je tombe sur la page du shell dash ?
Nicolas George a écrit :
Jette bash en faveur de zsh :
setopt extendedglob for f in **/*.(#i)tex; { ... frobincate $f }
Ah, j'ai peur de ne pas avoir le temps. Mais peut-être un jour... Ce n'est pas la première qu'on me parle en bien de zsh.
Aéris a écrit :
Y'en a pas vraiment. {} te permet juste de faire des trucs plus complexes, du style BIDULE=truc echo "${BIDULE}muche" Sans les accolades, ça serait impossible.
Et j'ai pris l'habitude de les mettre partout du coup =)
Ok, je vois. Perso, j'utilise les doubles quote :
BIDULE=truc echo "$BIDULE"muche
En tout cas, merci bien Aéris pour ta solution.
-- François Lafont
Le 22/05/2011 19:07, Xavier a écrit :
find /le/dossier/ -type f -exec f {} ;
Mais dans l'option -exec, la fonction f semble totalement inconnue et le
code ne fonctionne pas.
Faut exporter la fonction, et lancer un shell dans exec :
Ok, mais j'imagine pour le coup que les performances s'en trouvent
amoindries.
export func
find /dossier-type f -exec sh -c 'func $1' _ {} ;
Je crois qu'Aéris a parfaitement résolu mon problème, ceci étant, par
curiosité, j'ai essayé de faire fonctionner cette idée et je n'y suis
pas arrivé. J'ai fait ça :
function f(){
echo Traitement de $1
}
export f
find /le/dossier -type f -exec sh -c 'f $1' _ {} ;
Je ne comprends pas trop le «-c 'f $1'» et le underscore qui vient juste
après. J'ai bien tenté un "man sh", mais je tombe sur la page du shell
dash ?
Nicolas George a écrit :
Jette bash en faveur de zsh :
setopt extendedglob
for f in **/*.(#i)tex; {
... frobincate $f
}
Ah, j'ai peur de ne pas avoir le temps. Mais peut-être un jour... Ce
n'est pas la première qu'on me parle en bien de zsh.
Aéris a écrit :
Y'en a pas vraiment.
{} te permet juste de faire des trucs plus complexes, du style
BIDULE=truc
echo "${BIDULE}muche"
Sans les accolades, ça serait impossible.
Et j'ai pris l'habitude de les mettre partout du coup =)
Mais dans l'option -exec, la fonction f semble totalement inconnue et le code ne fonctionne pas.
Faut exporter la fonction, et lancer un shell dans exec :
Ok, mais j'imagine pour le coup que les performances s'en trouvent amoindries.
export func find /dossier-type f -exec sh -c 'func $1' _ {} ;
Je crois qu'Aéris a parfaitement résolu mon problème, ceci étant, par curiosité, j'ai essayé de faire fonctionner cette idée et je n'y suis pas arrivé. J'ai fait ça :
function f(){ echo Traitement de $1 } export f find /le/dossier -type f -exec sh -c 'f $1' _ {} ;
Je ne comprends pas trop le «-c 'f $1'» et le underscore qui vient juste après. J'ai bien tenté un "man sh", mais je tombe sur la page du shell dash ?
Nicolas George a écrit :
Jette bash en faveur de zsh :
setopt extendedglob for f in **/*.(#i)tex; { ... frobincate $f }
Ah, j'ai peur de ne pas avoir le temps. Mais peut-être un jour... Ce n'est pas la première qu'on me parle en bien de zsh.
Aéris a écrit :
Y'en a pas vraiment. {} te permet juste de faire des trucs plus complexes, du style BIDULE=truc echo "${BIDULE}muche" Sans les accolades, ça serait impossible.
Et j'ai pris l'habitude de les mettre partout du coup =)