ดูเหมือนว่า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อาจเป็นรูปแบบที่ไม่ดี แต่ดูเหมือนว่าวิธีที่ตรงที่สุดในการใช้ตัวกรอง regex เมื่อตะกี้
คำสั่งต่อไปนี้มีเฉพาะไฟล์ในผลลัพธ์การค้นหาและใช้เวลานานขึ้นอย่างเห็นได้ชัด
% find Workspace/ -type f | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-only.txt
ฉันเขียนโค้ดเพื่อทดสอบประสิทธิภาพของคำสั่งทั้งสองนี้ (ด้วยdashและtcshเพื่อแยกแยะผลกระทบใด ๆ ที่เชลล์อาจมีแม้ว่าจะไม่ควรมี) tcshผลที่ได้รับการละเว้นเพราะพวกเขากำลังหลักเดียวกัน
ผลลัพธ์ที่ฉันได้รับแสดงให้เห็นถึงโทษประสิทธิภาพ 10% -type f
นี่คือผลลัพธ์ของโปรแกรมที่แสดงจำนวนเวลาที่ใช้ในการดำเนินการซ้ำ 1,000 คำสั่งต่างๆ
% 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()อะไรก็ตามเพื่อดูว่าชื่อไฟล์ตรงกับไฟล์ไดเรกทอรี symlink ฯลฯ ฯลฯ ฉันทำstraceตามfind . และ a find . -type fและร่องรอยก็เกือบจะเหมือนกัน ต่างกันในการwrite()โทรที่มีชื่อไดเรกทอรีอยู่เท่านั้น ดังนั้นฉันไม่รู้ แต่ฉันอยากรู้คำตอบ
timeคำสั่ง builtin เพื่อดูว่าคำสั่งใช้เวลาในการประมวลผลนานแค่ไหนคุณไม่จำเป็นต้องเขียนสคริปต์ที่กำหนดเองเพื่อทดสอบ
findจะต้องตรวจสอบว่าเส้นทางที่กำหนดนั้นสอดคล้องกับไฟล์หรือไดเรกทอรีอยู่แล้วเพื่อที่จะเดินเนื้อหาของไดเรกทอรีซ้ำ ๆ - มันจะต้องตรวจสอบว่ามันเป็นไดเรกทอรีหรือไม่ก็ต้องตรวจสอบว่ามันเป็นไฟล์หรือไม่ มีประเภทรายการอื่น ๆ : ชื่อไปป์ลิงก์สัญลักษณ์บล็อกอุปกรณ์พิเศษซ็อกเก็ต ... ดังนั้นแม้ว่ามันอาจทำการตรวจสอบเรียบร้อยแล้วเพื่อดูว่ามันเป็นไดเรกทอรีหรือไม่