Dường như find
sẽ phải kiểm tra xem một đường dẫn cụ thể có tương ứng với một tệp hoặc thư mục hay không để đi theo cách đệ quy nội dung của các thư mục.
Đây là một số động lực và những gì tôi đã làm tại địa phương để thuyết phục bản thân rằng find . -type f
thực sự chậm hơn find .
. Tôi chưa đi sâu vào GNU tìm mã nguồn.
Vì vậy, tôi đang sao lưu một số tệp trong $HOME/Workspace
thư mục của mình và loại trừ các tệp phụ thuộc vào các dự án hoặc tệp kiểm soát phiên bản của tôi.
Vì vậy, tôi đã chạy lệnh sau đó thực hiện nhanh chóng
% find Workspace/ | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-and-dirs.txt
find
Đường ống grep
có thể là hình thức xấu, nhưng có vẻ như là cách trực tiếp nhất để sử dụng bộ lọc regex phủ định.
Lệnh sau chỉ bao gồm các tệp trong đầu ra của find và mất nhiều thời gian hơn.
% find Workspace/ -type f | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-only.txt
Tôi đã viết một số mã để kiểm tra hiệu năng của hai lệnh này (với dash
và tcsh
, chỉ để loại trừ bất kỳ hiệu ứng nào mà trình bao có thể có, mặc dù không nên có bất kỳ). Các tcsh
kết quả đã bị bỏ qua vì về cơ bản chúng giống nhau.
Kết quả tôi nhận được cho thấy mức phạt hiệu suất 10% cho -type f
Đây là đầu ra của chương trình hiển thị lượng thời gian cần thiết để thực hiện 1000 lần lặp của các lệnh khác nhau.
% 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
Đã thử nghiệm với
% find --version
find (GNU findutils) 4.4.2
Copyright (C) 2007 Free Software Foundation, Inc.
Trên Ubuntu 15.10
Đây là tập lệnh perl tôi đã sử dụng để đo điểm chuẩn
#!/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
và không có nó. Nhưng lần đầu tiên, nhân Linux đã tải nó vào bộ đệm và lần đầu tiên tìm thấy chậm hơn.
-type f
tùy chọn gây ra find
để gọi stat()
hoặc fstat()
bất cứ điều gì để tìm hiểu xem tên tệp có tương ứng với một tệp, thư mục, symlink, v.v. Tôi đã thực hiện strace
một find .
và một find . -type f
và dấu vết gần như giống hệt nhau, chỉ khác nhau trong các write()
cuộc gọi có tên thư mục trong đó. Vì vậy, tôi không biết, nhưng tôi muốn biết câu trả lời.
time
lệnh dựng sẵn để xem một lệnh mất bao lâu để thực thi, bạn không thực sự cần phải viết một tập lệnh tùy chỉnh để kiểm tra.
find
sẽ phải kiểm tra xem một đường dẫn cụ thể có tương ứng với một tệp hoặc thư mục hay không để đi theo cách đệ quy nội dung của các thư mục. - nó sẽ phải kiểm tra nếu nó là một thư mục, nó sẽ không phải kiểm tra xem nó có phải là một tập tin hay không. Có các loại mục nhập khác: ống có tên, liên kết tượng trưng, chặn các thiết bị đặc biệt, ổ cắm ... Vì vậy, mặc dù có thể đã thực hiện kiểm tra để xem đó có phải là một thư mục hay không, điều đó không có nghĩa là nó có phải là một tệp thông thường hay không.