[HS] un filtre 'find alike'
Le
Marc Chantreux

salut à tous,
j'aimerais beaucoup pouvoir utiliser find pour filtrer une liste de
chemins selon des critères de recherche. par exemple:
dpkg -L vim | find - -type f
ça n'est malheureusement pas possible. il existe de multiples
alternatives
une commande | while read p; do
test -f $p && echo $p
done
mais c'est chiant à écrire et pas super efficace sur de grosses listes
une commande | xargs -I% find % -prune -type f
qui va lancer 1 find par ligne :(
une commande | xargs -J% find % -prune -type f
qui marche sur les *BSD mais pas avec GNU xargs
et finalement ma préférée sous linux
une commande | perl -lne 'print if -f'
qui me fait degainer perl pour un truc aussi simple.
est ce que quelqu'un aurait une solution simple, efficace et qui marche
sous linux?
cordialement,
marc
j'aimerais beaucoup pouvoir utiliser find pour filtrer une liste de
chemins selon des critères de recherche. par exemple:
dpkg -L vim | find - -type f
ça n'est malheureusement pas possible. il existe de multiples
alternatives
une commande | while read p; do
test -f $p && echo $p
done
mais c'est chiant à écrire et pas super efficace sur de grosses listes
une commande | xargs -I% find % -prune -type f
qui va lancer 1 find par ligne :(
une commande | xargs -J% find % -prune -type f
qui marche sur les *BSD mais pas avec GNU xargs
et finalement ma préférée sous linux
une commande | perl -lne 'print if -f'
qui me fait degainer perl pour un truc aussi simple.
est ce que quelqu'un aurait une solution simple, efficace et qui marche
sous linux?
cordialement,
marc
On 6/30/19 12:03 AM, Marc Chantreux wrote:
Je te l'accorde...
... tu es sûr de ça ? J'ai un doute, parce que "while" est un mot clé,
"read" et "test" sont built-in. Du coup, sauf erreur, il n'y a pas de
fork sur la partie droite du pipe et j'aurais donc dis que ça doit être
justement plutôt efficace sur de grosses listes. Je me trompe ?
Personnellement, c'est la commande que j'aurais utilisée.
--
François Lafont
bon réellement j'ai dans mon .zshenv:
'?-' () while {read it} {"$@" $it && print $it}
du coup en vrai j'écris
une commande |?- test -f
mais si j'écris un script pour les collègues, je me force à ne pas
utiliser ce genre de shortcuts
d'experience, il n'y a pas photo: les filtres sont toujours plus
performants que les while loops.
d'un autre coté: j'ai acquis cette conviction il y a fort longtemps
(fin du millénaire dernier ) sans actualiser ni approffondir ...
alors j'ai fais un benchmark au doigt mouillé (le script ci-apres) qui
me permet de confirmer ...
sachant que:
* bash n'est pas présent dans le test parceque:
* c'est un shell que je n'utilise pas
* j'ai fais le test sur une box openbsd pour avoir xargs -J
* je n'ai même pas essayé avec xargs -I ... ce sera forcément tristoune
* zsh fait un bien mauvais score: je note mais ca n'est pas le sujet
alors je n'ai pas cherché à savoir si c'était perfectible
* perl forever o/
shell user kernel elapsed
ksh 0.75s 0.57s 1.33s
zsh 2.77s 4.97s 7.73s
sh 0.80s 0.53s 1.33s
xargs 0.13s 0.61s 0.74s
perl 0.07s 0.37s 0.44s
le script en question:
# creer un jeu de données
find . > sep---
cat sep---{,,,,,,,,,,,} > sep-0a
tr 'n' ' ' < sep-0a > sep-00
times=5
# lire le jeu une premiere fois histoire d'etre fair play
cat sep* > /dev/null
# while loop
script='
while read it; do
test -f "$it" && echo "$it"
done > /dev/null
'
print shell user kernel elapsed
for shell (ksh zsh sh) {
TIMEFMT="$shell %U %S %E"
< sep-0a time $shell -c $script
}
TIMEFMT="xargs %U %S %E"
< sep-00 time sh -c 'xargs -0 -J % find % -prune -type f > /dev/null 2>&1'
TIMEFMT="perl %U %S %E"
< sep-0a time sh -c ' perl -lne"print if -f" > /dev/null 2>&1 '