Lorsque l'on veut appliquer un traitement à des fichiers en parcourant l'arborescence. Il y a la possibilité d'utiliser la commande find associé à - exec.
Voici quelques exemples du monde réel world FIND usage
Copie dans un répertoirefind / -type f -name *.jpg -exec cp {} . \;find /home/hudson/repertoire-data/ -type f -regex ".*ARTICLE_O.*" -exec echo {} \;find /home/hudson/repertoire-data/ -type f -regex ".*ARTICLE_[^O].*" -exec echo {} \;find . -type f -size +10000 -exec ls -al {} \;Récherche des fichiers accédés il y a un jourfind . -atime +1 -type f -exec mv {} TMP \; find . -name "-F" -exec rm {} \; # a script error created a file called -F find . -exec grep -i "vds admin" {} \;find . \! -name "*.Z" -exec compress -f {} \;find . -type f \! -name "*.Z" \! -name ".comment" -print | tee -a /tmp/listfind . -exec chmod 775 {} \;find . -user xuser1 -exec chown -R user2 {} \;find . -exec grep PW0 {} \;find . -exec grep -i "pw0" {} \;find . -atime +6find . -atime +6 -exec ll | morefind . -atime +6 -exec ll | more \;find . -name auth*find . -exec grep -i plotme10 {} \;find . -ls -exec grep 'PLOT_FORMAT 22' {} \;find . -print -exec grep 'PLOT_FORMAT 22' {} \;find . -print -exec grep 'PLOT_FORMAT' {} \;find . -print -exec grep 'PLOT_FORMAT' {} \;find ./machbook -exec chown 184 {} \;find . \! -name '*.Z' -exec compress {} \;find . \! -name "*.Z" -exec compress -f {} \;find /raid/03c/ecn -xdev -type f -printfind /raid/03c/ecn -xdev -path -type f -printfind / -name .ssh* -print | tee -a ssh-stufffind . -name "*font*"find . -name hpmcad*find . -name *fnt*find . -name hp_mcad* -printfind . -grep Pld {} \;find . -exec grep Pld {} \;find . -exec grep Pld {} \;find . -exec grep PENWIDTH {} \; | morefind . -name config.profind /raid -type d -name ".local_sd_customize" -printfind /raid -type d -name ".local_sd_customize" -ok cp /raid/04d/MCAD-apps/I_Custom/SD_custom/site_sd_customize/user_filer_project_dirs {} \;find /raid -type d -name ".local_sd_customize" -exec cp /raid/04d/MCAD-apps/I_Custom/SD_custom/site_sd_customize/user_filer_project_dirs {} \;find . -name xeroxreleasefind . -exec grep xeroxrelease {} \;find . -name xeroxreleasefind . -name xeroxrelease* -print 2>/dev/nullfind . -name "*release*" 2>/dev/nullfind / -name "*xerox*" 2>/dev/nullfind . -exec grep -i xeroxrelease {} \;find . -print -exec grep -i xeroxrelease {} \;find . -print -exec grep -i xeroxrelease {} \; > xeroxrel.lisfind . -exec grep -i xeroxrel {} \;find . -print -exec grep -i xeroxrel {} \;find . -print -exec grep -i xeroxrel {} \; | morefind /raid/03c/inwork -xdev -type f -print >> /raid/04d/user_scripts/prt_list.tmpfind . -exec grep '31.53' {} \;find . -ls -exec grep "31/.53" {} \; > this.lisfind . -print -exec grep "31/.53" {} \; > this.lisfind . -print -exec grep 31.53 {} \; > this.lisfind . -exec grep -i pen {} /;find . -exec grep -i pen {} \;find . -print -exec grep -i pen {} \; | morefind . -exec grep -i pen {} \;find . -atime +6 -exec ll | more \;find . -atime +6 -exec ll \;find . -atime +6 -exec ls \;find . -atime +30 -exec ls \;find . -atime +30 -exec ls \; | wc -lfind . \! -name '*.Z' -exec compress -f {} \;find . -name 'cache*' -depth -exec rm {} \;find . -name 'cache*' -depth -print | tee -a /tmp/cachefilesfind . -name 'cache[0-9][0-9]*' -depth -print | tee -a /tmp/cachefilesfind . -name 'hp_catfile' 'hp_catlock' -depth -print | tee -a /tmp/hp.catsfind . -name 'hp_catfile' -name 'hp_catlock' -depth -print | tee -a /tmp/hp.catsfind . -name 'hp_cat*' -depth -print | tee -a /tmp/hp.catsfind . -name 'hp_cat[fl]*' -depth -print | tee -a /tmp/hp.catsfind /raid -name 'hp_cat[fl]*' -depth -printfind . \! -name '*.Z' -exec compress -f {} \;find . -name '*' -exec compress -f {} \;find . -xdev -name "wshp1*" -printfind . -xdev -name "wagoneer*" -printfind . -name "xcmd" -depth -printfind /usr/contrib/src -name "xcmd" -depth -printfind /raid -type d -name ".local_sd_customize" -exec ls {} \; find /raid -type d -name ".local_sd_customize" \ -exec cp /raid/04d/MCAD-apps/I_Custom/SD_custom/site_sd_customize/user_filer_project_dirs {} \;
L'inconvénient de la méthode find est qu'elle passe par l'interpréteur de commande pour lancer le shell ce qui peut-être problématique lorsque l'on souhaite traiter des fichiers ayant des noms comportant des espaces, guillemets, parenthèse etc.
La seconde solution est de faire un programme C pour appliquer son traitement. La librairie ftw adresse spécialement ce type de problème, elle fonctionne comme la commande find.
Ses paramètres sont
* Le chemin de départ de la récursion
* La méthode à appeler pour chaque élement (Le nom peut varier mais elle doit retourner un entier et avoir trois arguments.
int nomdemethode(const char *path, const struct stat *ptr, int flag))
Voici un exemple :
#include <ftw.h>#include <stdio.h>int process(const char *path, const struct stat *ptr, int flag){ printf("Found\n path:%s\nflag%d\n", path, flag); return 0;}int main(int argc, char *argv[]) { if(argc == 1){ ftw(".", process, 1);} else{ ftw(argv[1], process, 1);} return 0;}
Exemple d'utilisation :
Je voulais appliquer un traitement audio à de nombreux fichiers par le biais de la commande sox, malheureusement ce programme n'avait pas de fonction qui permettait d'effectuer des traitements par lots.
Les noms de fichiers comportaient aussi de nombreux caractères spéciaux qui empêchaient l'utilisation de la commande find. J'ai adapté le source du programme.
- Renommer la méthode main de sox par une méthode ancienmain
- Utiliser la méthode main du type présenté plus haut
- Créer une méthode appelée à chaque fois que ftw rencontre un nouvel élément on l'appelle process.
int process(char *dirname, const struct stat *status, int type){ if(!(type == FTW_F && strstr(dirname,".mp3")!=NULL&& strstr(dirname,"/L-")==NULL)){ return 0; }
Il ne s'agit clairement pas d'un controunement facile, et la volumétrie des fichiers doit clairement compenser l'effort de programmation par rapport à un appel de find.