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.321suser 0m0.170ssys 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.developpez.net/forums/d133567/systemes/linux/applications/shell/option-prune-commande-find/

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 !