Find prune
Trouver des prunes ou find -prune
C'est vrai que notre ami GNU find est efficace, rapide etc….
Mais quand nous voulons cherchez dans une arborescence il arrive que nous souhaitons exclure des répertoires. Un façon de faire est -not -wholename
Ça marche, donc où est le problème ? Et bien si nous suivons ce que fait find à l'aide de la commande strace, nous nous apercevons qu'il recherche malgré tout dans le dossier qu'y était pourtant exclu.
Dans notre exemple, nous avons un dossier 1wpixwnr.default dans .thunderbird
Et nous voulons tous les fichiers du répertoire courant sauf ceux présents dans .thunderbird
Ici nous constatons que find va dans .thunderbird, puisqu'il ouvre 1wpixwnr.default
# strace find . -not -wholename ".thunderbird/*" 2>&1 |grep '1wpixwnr.default'|grep ^open
open("1wpixwnr.default", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 5
Même chose ici
# strace find . -not -wholename "./.thunderbird/*" 2>&1 |grep '1wpixwnr.default'|grep ^open open("1wpixwnr.default", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 5
Alors qu'avec des prunes, il n'y a que les accès disque nécessaires
strace find . -wholename "./.thunderbird/*" -prune -o -print 2>&1 |grep '1wpixwnr.default'|grep ^open
Attention cependant, ici même avec prune, il y a des accès disques inutiles
# strace find . -wholename ".thunderbird/*" -prune -o -print 2>&1 |grep '1wpixwnr.default'|grep ^open
open("1wpixwnr.default", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 5
Notons qu'ici .thunderbird est inclus dans le résultat :
$ find . -wholename "./.thunderbird/*" -prune -o -print |grep '\.thunderbird' ./.thunderbird
A présent comparons :
$ time find . -not -wholename "./Ziques/*" >/dev/null
real 0m0.321s user 0m0.170s sys 0m0.140s </code>
(encore une fois)
$ time find . -not -wholename "./Ziques/*" >/dev/null real 0m0.321s user 0m0.170s sys 0m0.140s
$ time find . -wholename "./Ziques/*" -prune -o -print >/dev/null real 0m0.138s user 0m0.100s sys 0m0.030s
Alors que le résultat est identique :
diff <(find . -not -wholename "./Ziques/*") <(find . -wholename "./Ziques/*" -prune -o -print)
Quelques liens sur find -prune que je n'ai pas vraiment eu le temps de lire.
http://www.liamdelahunty.com/tips/linux_find_exclude_multiple_directories.php
http://www.liamdelahunty.com/tips/linux_find_prune_directory.php
http://dit-archives.epfl.ch/FI94/5-94-page15.html
Exemple :
Trouvez tous les mp3 qui ne sont pas dans ./backup/Ziques :
find . -type f -iname "*.mp3" \( -wholename "./backup/Ziques/*" -prune -o -print \)
Évidement on peut faire :
find . -type f -iname "*.mp3" -not -wholename "./backup/Ziques/*"
Mais dans ce cas find ira quand même dans l'arborescence ./backup/Ziques et ça peut être long !
