Parece que find
seria necessário verificar se um determinado caminho corresponde a um arquivo ou diretório de qualquer maneira para percorrer recursivamente o conteúdo dos diretórios.
Aqui estão algumas motivações e o que eu fiz localmente para me convencer de que find . -type f
é realmente mais lento do que find .
. Ainda não procurei no código-fonte do GNU find.
Portanto, estou fazendo backup de alguns arquivos no meu $HOME/Workspace
diretório e excluindo arquivos que são dependências dos meus projetos ou arquivos de controle de versão.
Então eu executei o seguinte comando que executou rapidamente
% find Workspace/ | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-and-dirs.txt
find
canalizado grep
pode ter uma forma incorreta, mas parecia a maneira mais direta de usar um filtro regex negado.
O comando a seguir inclui apenas arquivos na saída de localização e levou muito mais tempo.
% find Workspace/ -type f | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-only.txt
Eu escrevi um código para testar o desempenho desses dois comandos (com dash
e tcsh
, apenas para descartar quaisquer efeitos que o shell possa ter, mesmo que não deva haver). Os tcsh
resultados foram omitidos porque são essencialmente os mesmos.
Os resultados obtidos mostraram uma penalidade de desempenho de 10% para -type f
Aqui está a saída do programa mostrando a quantidade de tempo necessário para executar 1000 iterações de vários 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
Testado com
% find --version
find (GNU findutils) 4.4.2
Copyright (C) 2007 Free Software Foundation, Inc.
No Ubuntu 15.10
Aqui está o script perl que eu usei para fazer benchmarking
#!/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
e sem ele. Mas, pela primeira vez, o kernel Linux o carregou no cache e a primeira descoberta foi mais lenta.
-type f
opção causada find
chamar stat()
ou fstat()
ou qualquer outra coisa, a fim de descobrir se o nome do arquivo corresponde a um arquivo, um diretório, um link simbólico, etc etc. Eu fiz uma strace
em uma find .
e uma find . -type f
e o traço era quase idêntico, diferindo apenas nas write()
chamadas que continham nomes de diretório. Então, eu não sei, mas quero saber a resposta.
time
comando interno para ver quanto tempo um comando leva para ser executado; você realmente não precisava escrever um script personalizado para testar.
find
seria necessário verificar se um determinado caminho corresponde a um arquivo ou diretório de qualquer maneira para percorrer recursivamente o conteúdo dos diretórios. - teria que verificar se é um diretório, não precisaria verificar se é um arquivo. Existem outros tipos de entrada: pipes nomeados, links simbólicos, bloquear dispositivos especiais, soquetes ... Portanto, embora já tenha feito a verificação para ver se é um diretório, isso não significa que ele saiba se é um arquivo comum.