検索コマンド:特定のフォルダのファイルパターンを除外

検索コマンド:特定のフォルダのファイルパターンを除外

findフォルダ内の特定のファイルパターンを除いて、そのフォルダのサブフォルダには除外するコマンドが必要です。たとえば、除外したい場合、subdir1/subdir1.1/UndesiredFiles*.tgzアスタリスクはフォルダ名の区切り文字を含む連続した文字と一致するため、以下は機能しません/

find * -not -path 'subdir1/subdir1.1/UndesiredFiles*.tgz'

上記では除外したくない次の項目を除外します。

subdir1/subdir1.1/UndesiredFilesAndMore/*.tgz
subdir1/subdir1.1/UndesiredFilesAndMore/StillMore/*.tgz

私はGnufindバージョン4.9.0を使用しています。

ベストアンサー1

一部findの実装では、シェルのglobパターンの代わりに正規表現(実装とオプション、または他の述語によってバリエーションが異なります)を使用することを除いて、同じ述語をサポートしています-regex。非標準のBSDスタイル述語をサポートしている-pathことを考慮すると、おそらくそれらの1つです。find-not

LC_ALL=C find . ! -regex '\./subdir1/subdir1\.1/UndesiredFiles[^/]*\.tgz'

*glob演算子(regexpと同じ.*:0個以上の文字)をregexp [^/*](0個以上の文字を除く/)に置き換えます。

正規表現はデフォルトで固定されているため、明示的または^必須ではありません$

すべての文字に一致する正規表現演算子と同様に、リテラルのみに一致するようにエスケープを.使用する必要があります\.[.]可能であっても)。 sはファイル名で非常に一般的な.ので見落としがちです。.

LC_ALL=Cすべてのファイル名とディレクトリ名がユーザーロケールの有効な文字でのみ構成されることを保証できない場合は、通常必須です(これは-pathbtwにも適用されます)。

BSDでは標準の基本正規表現を使用し、-regexforやなどのオプションを使用して標準拡張正規表現に変更できます。 GNUの場合、デフォルトではこれはemacs正規表現の古代バージョンですが、他のさまざまなバージョンに変更される可能性があります。-Egrepsedfind-regextypeスルブ。それにもかかわらず、上記の特定の正規表現はどんな変形でも機能します。


findサポートされていない場合は、次のことが-regexできます。

LC_ALL=C find . ! '(' -path './subdir1/subdir1.1/UndesiredFiles*.tgz' \
  ! -path './subdir1/subdir1.1/*/*' ')'

つまり、1つ以上を含む一致を./subdir1/subdir1.1/UndesiredFiles*.tgz除いてフィルタリングします。*/

または、perl以下をフィルタリングできます。

find . -exec printf '%s\0' {} + |
  perl -l -0ne 'print unless m{^\Q./subdir1/subdir1.1/UndesiredFiles\E[^/]*\.tgz\z}'

ここでは、\Q...\E内容を固定文字列として処理して正規表現演算子をエスケープする必要はありません。ここでは、正規表現を^始めと終わりに固定する必要があります(正規表現は、末尾または末尾の改行がPerlで一致しないため、ファイルが「間違って」除外されます)。\z$$'UndesiredFiles.tgz\n'

(パスを引数として使用してコマンドを実行して置き換えprintますsystem "cmd", $_

一部(ほとんど)のfind実装は-exec printf '%s\0' {} +で置き換えることができます-print0。一部のxargs実装では、-0またはオプションで-d '\0'この出力形式をサポートしています。

find . -print0 |
  perl -0 -lne 'print unless m{^\Q./subdir1/subdir1\.1/UndesiredFiles\E[^/]*\.tgz\z}' |
  xargs -r0 cmd

-lオプションが移動しました後ろに -0出力レコード区切り記号も NUL です。


zshシェルを使用する場合はこれは必要ありませんfind。次のことができます。

set -o extendedglob
print -rC1 -- **/*~subdir1/subdir1.1/UndesiredFiles[^/]#.tgz(ND)

ここで#正規表現と同等のExtendedglobは次の*とおりです。~とは別に/まさかand演算子は、一致するグローバル拡張動作に(ND)適用されますnullglob(一致しない場合は何も拡張されません)と(隠しファイルを含む)。 matchの動作をさらに一致させるために、リストに修飾子を追加することもできます。dotglobfindoNNofind

print -rC1 -- printr■列です1 Cが、もちろん別のコマンドを使用したり、リストを繰り返すこともできますfor

**/*(サブディレクトリの数に関係なく、すべての名前を持つすべてのファイルと一致、省略)このオプションが設定されていると、(*/)#*省略できます。**globstarshort


とにかく、これらすべては除外されますが./subdir1/subdir1.1/UndesiredFiles-whatever.tgzいいえ除外./subdir1/subdir1.1/UndesiredFiles-whatever.tgz/other/fileパターンを調整するか、-prune find述語を使用して除外する必要があります。

おすすめ記事