私は(2Tドライブの約900,000個のファイルのうち)無関係なファイルを見つけて識別する必要があることに気づきました。アーカイブしたいファイルがたくさんあり、これらが良好であることが知られているファイルのファイル名パターンがあります。私が望むのは、どのパターンとも一致しないファイルを見つけることです。
ファイル名パターンリストと一致しないファイルを見つけるには?
実行してfind
すべてのファイルのリストを取得し、grep -v
その結果をファイルに保存されているパターンのリストと共に使用できます。これが標準的な方法ですか、それともこれらの不適合ファイルを見つけるためのきちんとした方法はありますか?
説明 - 回答に基づいて追加情報を提供します。私は多数のパターン(20以上、おそらく100以上)を持つことを期待し、それをファイルに保存したい、そしてもちろん新しいパターンを追加する簡単な方法が欲しいです。多くの照会パラメータを直接(壊れやすく)編集することは避けたいのですが、リストを作成すると効果がある可能性があります。
答え1
find(1)
あなたのニーズを満たすのに十分強力です。括弧を使用して、一致するすべての名前を式として収集し、それを否定して表示します。不適格ファイル名。たとえば、すべてのファイルを表示します。いいえ名前は*.txt
、*.bz2
または*.zip
:
$ find . \! \( -name \*.txt -o -name \*.bz2 -o -name \*.zip \)
代わりにGNUとBSDを使用できます-not
。 POSIXと互換性がありませんが、シェルがそれを解釈しないようにエスケープする必要はありません。\!
find
ファイルのパターンに基づいて式を作成するには、シェルスクリプトを作成します。
#!/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
固定位置にあると予想する代わりに、スキーマファイル名を引数として渡します。
スキーマファイルを元の場所に残して
-o -name .fnpatterns
ビルドfind
コマンドに追加すると、出力には表示されません。 (これはまた、ハッカーがビルド式のリードをshift
「食べる」ことを防ぎます。)-o
find
または、同様のコマンドを使用してコマンドにアクションを追加します-exec
。スキーマファイルに空白行またはコメントを許可します。
答え2
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
最後にあるものを.
歩きたい木の上に変えてください。