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の出力に含まれるファイルのみが含まれ、著しく時間がかかりました。
% find Workspace/ -type f | grep -v '/vendor|/node_modules/|Workspace/sources/|/venv/|/.git/' > ws-files-only.txt
これら2つのコマンドのパフォーマンスをテストするためのコードをいくつか作成しました(dash
を使用) およびtcsh
、シェルが持つ可能性のある影響を除外するためだけに、存在してはならない場合でも)。 tcsh
結果は基本的に同じであるため、省略されています。
私が得た結果は、-type f
に対して約10%のパフォーマンスペナルティを示しました。
これは、さまざまなコマンドの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.
Ubuntu15.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 "%snn", time_command(@$shell, $command);
}
}
承認された回答:
GNU findには、find .
に適用できる最適化があります。 ただし、find . -type f
:ディレクトリ内の残りのエントリがいずれもディレクトリではないことがわかっている場合は、ファイルタイプをわざわざ判断する必要はありません(stat
を使用)。 システムコール)検索条件の1つがそれを必要としない限り。 stat
を呼び出す 情報は通常、含まれているディレクトリではなく、ディスク上の別の場所にあるiノードにあるため、測定可能な時間がかかる場合があります。
どうやって知るの?ディレクトリのリンク数は、そのディレクトリにあるサブディレクトリの数を示しているためです。一般的なUnixファイルシステムでは、ディレクトリのリンク数は2にディレクトリの数を加えたものです。1つは親のディレクトリのエントリ用で、もう1つは.
エントリ、および..
用に1つ 各サブディレクトリのエントリ。
-noleaf
オプションはfind
に指示します この最適化を適用しないでください。これは、find
の場合に便利です ディレクトリリンク数がUnixの規則に従わないファイルシステムで呼び出されます。