Il semble qu'il find
faudrait de toute façon vérifier si un chemin donné correspond à un fichier ou un répertoire afin de parcourir récursivement le contenu des répertoires.
Voici une motivation et ce que j'ai fait localement pour me convaincre que c'est find . -type f
vraiment plus lent que find .
. Je n'ai pas encore fouillé dans le code source de GNU find.
Je sauvegarde donc certains fichiers de mon $HOME/Workspace
répertoire et j'exclus les fichiers qui sont soit des dépendances de mes projets, soit des fichiers de contrôle de version.
J'ai donc exécuté la commande suivante qui s'est exécutée rapidement
% find Workspace/ | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-and-dirs.txt
find
canalisé à grep
peut - être mauvaise forme, mais il semblait que la façon la plus directe d'utiliser un filtre regex niée.
La commande suivante inclut uniquement les fichiers dans la sortie de find et a pris sensiblement plus de temps.
% find Workspace/ -type f | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-only.txt
J'ai écrit du code pour tester les performances de ces deux commandes (avec dash
et tcsh
, juste pour exclure tout effet que le shell pourrait avoir, même s'il ne devrait pas y en avoir). Les tcsh
résultats ont été omis car ils sont essentiellement les mêmes.
Les résultats que j'ai obtenus montrent une pénalité de 10% -type f
Voici la sortie du programme indiquant le temps nécessaire pour exécuter 1000 itérations de diverses commandes.
% perl tester.pl
/bin/sh -c find Workspace/ >/dev/null
82.986582
/bin/sh -c find Workspace/ | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > /dev/null
90.313318
/bin/sh -c find Workspace/ -type f >/dev/null
102.882118
/bin/sh -c find Workspace/ -type f | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > /dev/null
109.872865
Testé avec
% find --version
find (GNU findutils) 4.4.2
Copyright (C) 2007 Free Software Foundation, Inc.
Sur Ubuntu 15.10
Voici le script Perl que j'ai utilisé pour l'analyse comparative
#!/usr/bin/env perl
use strict;
use warnings;
use Time::HiRes qw[gettimeofday tv_interval];
my $max_iterations = 1000;
my $find_everything_no_grep = <<'EOF';
find Workspace/ >/dev/null
EOF
my $find_everything = <<'EOF';
find Workspace/ | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > /dev/null
EOF
my $find_just_file_no_grep = <<'EOF';
find Workspace/ -type f >/dev/null
EOF
my $find_just_file = <<'EOF';
find Workspace/ -type f | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > /dev/null
EOF
my @finds = ($find_everything_no_grep, $find_everything,
$find_just_file_no_grep, $find_just_file);
sub time_command {
my @args = @_;
my $start = [gettimeofday()];
for my $x (1 .. $max_iterations) {
system(@args);
}
return tv_interval($start);
}
for my $shell (["/bin/sh", '-c']) {
for my $command (@finds) {
print "@$shell $command";
printf "%s\n\n", time_command(@$shell, $command);
}
}
-type f
et sans lui. Mais au début, le noyau Linux l'a chargé dans le cache et la toute première découverte a été plus lente.
-type f
option provoquait l' find
appel stat()
ou fstat()
ou quoi que ce soit afin de savoir si le nom du fichier correspondait à un fichier, un répertoire, un lien symbolique, etc. J'ai fait un strace
sur un find .
et un find . -type f
et la trace était presque identique, ne différant que par les write()
appels contenant des noms de répertoire. Donc, je ne sais pas, mais je veux connaître la réponse.
time
commande intégrée pour voir combien de temps une commande prend pour s'exécuter, vous n'aviez pas vraiment besoin d'écrire un script personnalisé pour tester.
find
faudrait de toute façon vérifier si un chemin donné correspond à un fichier ou un répertoire afin de parcourir récursivement le contenu des répertoires. - il devrait vérifier s'il s'agit d'un répertoire, il ne devrait pas vérifier s'il s'agit d'un fichier. Il existe d'autres types d'entrées: canaux nommés, liens symboliques, blocs périphériques spéciaux, sockets ... Donc, même s'il a peut-être déjà vérifié si c'est un répertoire, cela ne signifie pas qu'il sait s'il s'agit d'un fichier normal.