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 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.
우분투 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);
}
}
답변1
find .
GNU find에는 적용할 수 있지만 적용할 수 없는 최적화가 있습니다 . 디렉터리의 나머지 항목 중 어느 것도 디렉터리가 아니라는 것을 알고 있으면 검색 중 하나가 아닌 한 find . -type f
(시스템 호출을 사용하여) 파일 형식을 결정하지 않습니다. stat
조건이 필요합니다. stat
정보는 일반적으로 포함된 디렉터리가 아닌 디스크의 별도 위치에 있는 inode에 있기 때문에 호출에 꽤 오랜 시간이 걸릴 수 있습니다.
어떻게 알 수 있나요? 디렉토리의 링크 수는 해당 디렉토리에 있는 하위 디렉토리 수를 나타내기 때문입니다. 일반적인 Unix 파일 시스템에서 디렉터리의 링크 수는 2에 디렉터리 수를 더한 값입니다. 상위 디렉터리의 디렉터리 항목은 1, 각 하위 디렉터리의 항목은 1 , 각 하위 디렉터리의 항목은 .
1입니다 ...
이 -noleaf
옵션은 find
이 최적화가 적용되지 않아야 함을 나타냅니다. 이는 find
디렉터리 링크 계산이 Unix 규칙을 따르지 않는 특정 파일 시스템에서 호출되는 경우 유용합니다.