ดูเหมือนว่า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
จะต้องตรวจสอบว่าเส้นทางที่กำหนดนั้นสอดคล้องกับไฟล์หรือไดเรกทอรีอยู่แล้วเพื่อที่จะเดินเนื้อหาของไดเรกทอรีซ้ำ ๆ - มันจะต้องตรวจสอบว่ามันเป็นไดเรกทอรีหรือไม่ก็ต้องตรวจสอบว่ามันเป็นไฟล์หรือไม่ มีประเภทรายการอื่น ๆ : ชื่อไปป์ลิงก์สัญลักษณ์บล็อกอุปกรณ์พิเศษซ็อกเก็ต ... ดังนั้นแม้ว่ามันอาจทำการตรวจสอบเรียบร้อยแล้วเพื่อดูว่ามันเป็นไดเรกทอรีหรือไม่