Parece que find
tendría que verificar si una ruta determinada corresponde a un archivo o directorio de todos modos para recorrer recursivamente el contenido de los directorios.
Aquí hay algo de motivación y lo que he hecho localmente para convencerme de que find . -type f
realmente es más lento que find .
. Todavía no he profundizado en el código fuente de búsqueda de GNU.
Así que estoy haciendo una copia de seguridad de algunos de los archivos en mi $HOME/Workspace
directorio y excluyendo los archivos que son dependencias de mis proyectos o archivos de control de versiones.
Así que ejecuté el siguiente comando que se ejecutó rápidamente
% find Workspace/ | grep -v '/vendor|/node_modules/|Workspace/sources/|/venv/|/.git/' > ws-files-and-dirs.txt
find
canalizado a grep
puede ser una mala forma, pero parecía la forma más directa de usar un filtro de expresiones regulares negado.
El siguiente comando incluye solo archivos en la salida de find y tomó mucho más tiempo.
% find Workspace/ -type f | grep -v '/vendor|/node_modules/|Workspace/sources/|/venv/|/.git/' > ws-files-only.txt
Escribí un código para probar el rendimiento de estos dos comandos (con dash
y tcsh
, solo para descartar cualquier efecto que pueda tener el caparazón, aunque no debería haber ninguno). El tcsh
se han omitido los resultados porque son esencialmente los mismos.
Los resultados que obtuve mostraron una penalización de rendimiento del 10 % para -type f
Aquí está el resultado del programa que muestra la cantidad de tiempo necesario para ejecutar 1000 iteraciones de varios comandos.
% 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
Probado con
% find --version
find (GNU findutils) 4.4.2
Copyright (C) 2007 Free Software Foundation, Inc.
En Ubuntu 15.10
Aquí está el script de Perl que utilicé para la evaluación comparativa
#!/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 "%snn", time_command(@$shell, $command);
}
}
Respuesta aceptada:
GNU find tiene una optimización que se puede aplicar a find .
pero no para find . -type f
:si sabe que ninguna de las entradas restantes en un directorio son directorios, entonces no se molesta en determinar el tipo de archivo (con stat
llamada del sistema) a menos que uno de los criterios de búsqueda lo requiera. Llamando a stat
puede llevar un tiempo medible ya que la información normalmente está en el inodo, en una ubicación separada en el disco, en lugar del directorio contenedor.
¿Cómo lo sabe? Porque el recuento de enlaces en un directorio indica cuántos subdirectorios tiene. En los sistemas de archivos típicos de Unix, el recuento de enlaces de un directorio es 2 más el número de directorios:uno para la entrada del directorio en su padre, uno para el .
entrada y otra para el ..
entrada en cada subdirectorio.
El -noleaf
opción le dice a find
para no aplicar esta optimización. Esto es útil si find
se invoca en algún sistema de archivos donde los recuentos de enlaces de directorio no siguen la convención de Unix.