(2Tドライブ上の約900Kファイルのうち)無関係なファイルを見つけて識別する必要があることに気づきました。保持したいファイルがたくさんあり、これらの既知の適切なファイルのファイル名パターンがあります。私が欲しいのは、どのパターンにも適合しないファイルを見つけることです。
ファイル名パターンのリストに一致しないファイルを見つけるにはどうすればよいですか?
find
を実行してすべてのファイルのリストを取得できます。grep -v
結果に、ファイルに保存されているパターンのリストを使用します。これは標準的な方法ですか、それともこれらの非準拠ファイルを見つける簡単な方法はありますか?
説明-回答に基づいて、ここにもう少し情報があります。多数のパターン(> 20、おそらく> 100)があると予想します。それらをファイルに保存し、簡単に新しい方法を追加したい(壊れやすい)findパラメータの大きなリストを直接編集することは避けたいですが、そのリストを作成するとうまくいくかもしれません。
Perlについて言及しているので...
#!/usr/bin/Perl
use strict;
use warnings;
use File::Find qw{find};
my %patterns;
while (<>) {
chomp;
$patterns{$_}++;
}
die "No pattern supplied\n" unless keys %patterns;
find(
sub{
my $matches_a_pattern=0;
for my $pattern (keys %patterns){
my $glob_pattern = $pattern;
for($glob_pattern){
s/\./\\./g;
s/\*/.*/g;
s/\?/./g;
}
$matches_a_pattern++ if ( /\Q$pattern\E/ or /$glob_pattern/);
}
print "$File::Find::name\n" unless $matches_a_pattern;
}
, '.' )
これを次のように呼び出します
/path/to/my/script file_with_patterns
.
最後に歩きたい木のてっぺん。
find(1)
は、必要なことを実行するのに十分強力です。かっこを使用してすべての準拠名を式にまとめ、次に否定してnon-conformingファイル名を表示します。たとえば、すべてのファイルを表示するにはnotという名前の*.txt
、*.bz2
、または*.Zip
:
$ find . \! \( -name \*.txt -o -name \*.bz2 -o -name \*.Zip \)
GNUおよびBSD find
を指定すると、-not
の代わりに\!
を使用できます。POSIXに準拠していませんが、エスケープは必要ありませんシェルがそれを解釈しないようにするため。
ファイル内のパターンから式を構築するには、シェルスクリプトの小さな問題です。
#!/bin/sh
set --
while IFS= read -r pattern
do
set -- "$@" -o "$pattern"
done < .fnpatterns
if [ $# -ne 0 ]; then
shift
set -- -not \( "$@" \)
fi
find . "$@"
これは、現在のディレクトリに.fnpatterns
というファイルがあり、1行に1つのパターンがあることを前提としています。上記のワンライナーを模倣するには、以下を含める必要があります。
*.txt
*.bz2
*.Zip
シェルスクリプトはパターンの*
文字をエスケープすることに注意してください。
これを任意に複雑にすることができます。いくつかのアイデア:
-type f
をfind
コマンドに追加して、ディレクトリではなく通常のファイルのみを表示するようにします。
固定された場所にあることを期待するのではなく、引数としてパターンファイル名を渡します
パターンファイルはそのままにしておきますが、ビルドされたfind
コマンドに-o -name .fnpatterns
を追加して、出力に表示されないようにします。 (これにより、ビルドされた式でshift
ハックがリード-o
を "食べる"必要もなくなります。)
-exec
などを使用して、find
コマンドにアクションを追加します。
パターンファイルで空白行またはコメントを許可する