Кажется, findчто в любом случае придется проверить, соответствует ли данный путь файлу или каталогу, чтобы рекурсивно просмотреть содержимое каталогов.
Вот некоторая мотивация и то, что я сделал на местном уровне, чтобы убедить себя, что на find . -type fсамом деле медленнее, чем find .. Я еще не копался в GNU найти исходный код.
Поэтому я создаю резервные копии некоторых файлов в моем $HOME/Workspaceкаталоге и исключаю файлы, которые являются либо зависимостями моих проектов, либо файлами контроля версий.
Итак, я запустил следующую команду, которая выполнялась быстро
% find Workspace/ | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-and-dirs.txt
findЭто grepможет быть плохая форма, но это кажется самым прямым способом использования отрицательного фильтра регулярных выражений.
Следующая команда включает в себя только файлы в выводе find и заняла заметно больше времени.
% find Workspace/ -type f | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-only.txt
Я написал некоторый код для проверки производительности этих двух команд (с dashи tcsh, просто чтобы исключить любые эффекты, которые может иметь оболочка, даже если их не должно быть). Эти tcshрезультаты были опущены , поскольку они по существу то же самое.
Результаты, которые я получил, показали около 10% снижения производительности за -type f
Вот выходные данные программы, показывающие количество времени, необходимое для выполнения 1000 итераций различных команд.
% 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
Протестировано с
% find --version
find (GNU findutils) 4.4.2
Copyright (C) 2007 Free Software Foundation, Inc.
На Ubuntu 15.10
Вот скрипт Perl, который я использовал для бенчмаркинга
#!/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и без него. Но вначале ядро Linux загрузило его в кеш, и самая первая находка была медленнее.
-type fпараметр вызвал findвызов stat()или fstat()что-то еще, чтобы выяснить, соответствует ли имя файла файлу, каталогу, символической ссылке и т. Д. И т. Д. Я сделал straceon find . и a, find . -type fи трассировка была почти идентична, отличается только write()вызовами, в которых были имена каталогов. Итак, я не знаю, но я хочу знать ответ.
timeвстроенная команда, чтобы увидеть, сколько времени занимает выполнение команды, вам не нужно было писать собственный скрипт для тестирования.
findчто в любом случае придется проверить, соответствует ли данный путь файлу или каталогу, чтобы рекурсивно просмотреть содержимое каталогов. - он должен проверить, является ли он каталогом, он не должен проверять, является ли он файлом. Существуют и другие типы записей: именованные каналы, символические ссылки, блочные специальные устройства, сокеты ... Так что, возможно, он уже выполнил проверку, чтобы определить, является ли это каталогом, но это не значит, что он знает, является ли он обычным файлом.