
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
私はこれらの2つのコマンドのパフォーマンスをテストするためにいくつかのコードを書いています(そしてを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.
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);
}
}
答え1
find .
GNU findには適用できますが適用できない最適化があります。ディレクトリの残りの項目のどれもディレクトリではないことがわかっている場合は、検索の1つでない限りfind . -type f
(システムコールを使用して)ファイルの種類を決定しません。stat
条件が必要です。stat
情報は通常、含まれているディレクトリではなくディスク上の別の場所にあるinodeにあるため、呼び出しにはかなり長い時間がかかることがあります。
どうすればわかりますか?ディレクトリ内のリンクの数は、そのディレクトリ内のサブディレクトリの数を表すためです。一般的な Unix ファイルシステムでは、ディレクトリのリンク数は 2 にディレクトリ数を加えた値です。親ディレクトリのディレクトリエントリは1、各サブディレクトリのエントリは1、各サブディレクトリのエントリは.
1です。..
この-noleaf
オプションは、find
この最適化が適用されないことを示します。これはfind
、ディレクトリリンク計算がUnixルールに従わない特定のファイルシステムで呼び出される場合に便利です。