Wygląda na to, findże musiałbym sprawdzić, czy dana ścieżka i tak odpowiada plikowi lub katalogowi, aby rekursywnie przechodzić przez zawartość katalogów.
Oto motywacja i to, co zrobiłem lokalnie, aby przekonać siebie, że find . -type fnaprawdę jest wolniejsze niż find .. Nie zagłębiłem się jeszcze w kod źródłowy GNU find.
Tworzę więc kopie zapasowe niektórych plików w moim $HOME/Workspacekatalogu i wykluczam pliki, które są albo zależnościami moich projektów, albo plikami kontroli wersji.
Uruchomiłem więc następujące polecenie, które wykonałem szybko
% find Workspace/ | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-and-dirs.txt
findprzesyłane strumieniowo do grepmoże być złej postaci, ale wydawało się, że jest to najbardziej bezpośredni sposób na użycie zanegowanego filtra regex.
Następujące polecenie zawiera tylko pliki w wyjściu find i zajęło zauważalnie więcej czasu.
% find Workspace/ -type f | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-only.txt
Napisałem trochę kodu, aby przetestować działanie tych dwóch poleceń (z dashi tcsh, aby wykluczyć jakiekolwiek efekty, jakie może mieć powłoka, nawet jeśli nie powinno być żadnych). Te tcshwyniki zostały pominięte, ponieważ są w zasadzie takie same.
Wyniki, które uzyskałem, pokazały około 10% kary za wydajność -type f
Oto wynik programu pokazujący czas potrzebny do wykonania 1000 iteracji różnych poleceń.
% 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
Testowane z
% find --version
find (GNU findutils) 4.4.2
Copyright (C) 2007 Free Software Foundation, Inc.
Na Ubuntu 15.10
Oto skrypt perla, którego użyłem do testów porównawczych
#!/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 fi bez niego. Ale po raz pierwszy jądro Linuksa załadowało go do pamięci podręcznej i pierwsze wyszukiwanie było wolniejsze.
-type fopcja spowodowała findwywołanie stat()lub fstat()cokolwiek innego, aby dowiedzieć się, czy nazwa pliku odpowiada plikowi, katalogowi, dowiązaniu symbolicznemu itp. Zrobiłem stracena A find . i A, find . -type fa ślad był prawie identyczny, różni się tylko write()połączeniami, które zawierają nazwy katalogów. Nie wiem, ale chcę znać odpowiedź.
timewbudowane polecenie, aby zobaczyć, jak długo trwa wykonanie polecenia, tak naprawdę nie trzeba pisać niestandardowego skryptu, aby przetestować.
findże musiałbym sprawdzić, czy dana ścieżka i tak odpowiada plikowi lub katalogowi, aby rekursywnie przechodzić przez zawartość katalogów. - musiałby sprawdzić, czy jest to katalog, nie musiałby sprawdzić, czy jest to plik. Istnieją inne typy wpisów: nazwane potoki, dowiązania symboliczne, blokuj urządzenia specjalne, gniazda ... Więc chociaż mógł już sprawdzić, czy jest to katalog, nie znaczy to, że wie, czy jest to zwykły plik.