いくつかのサブディレクトリとファイルを含むディレクトリX
がある場合、正規表現^rf.*\.img$
に一致するファイル名を(直接的または間接的に)含むX
の直接の子ディレクトリの名前をリストしたいと思います。
これはOSXでどのように実現できますか?
GNU find
を使用すると、各ディレクトリをテストできます。
for i in "$dir"/*/
do
test -n "$(find "$i" -type f -regex '.*/test[^/]*' -print -quit)" \
&& echo "$i"
done
これにより、各ディレクトリでtest
で始まるファイルが検索され、見つかった場合はそのディレクトリが出力されます。
注意すべき点がいくつかあります。
.
で始まるサブディレクトリは無視しています。それらを考慮する必要がある場合は、.
および..
をキャッチせずにそれらを含める方法についてBash FAQを確認してください。-quit
を使用して、find
を早期に終了します。これにより、大きなファイルシステムツリーで時間を節約できます。-regex
テストは、find
によって考慮されるパス名全体と照合されるため、ベース名と照合するだけの場合は、/
との照合に注意する必要があります。 -filename
を使用して、この制限なしで(そして、GNU find)を必要とせずに)ワイルドカードパターンを照合できます。-iregex
の代わりに-regex
を使用できます。-regextype
オプションを使用して正規表現構文を選択できます。質問の特定のパターンについては、ワイルドカードを使用できるため、次のようになります。
for i in "$dir"/*/
do
test -n "$(find "$i" -type f -name 'rf*.img' -print -quit)" && echo "$i"
done
zsh
を使用する場合(すでにX
にいると仮定):
typeset -U subdirs
subdirs=(*/**/rf*.img(.e_'REPLY=${REPLY%%/*}'_))
print -rl -- "${subdirs[@]}"
ここに */**/rf*.img
すべてのグロブrf*.img
すべてのサブディレクトリ内のファイル、glob修飾子.
とe
は通常のファイルのみを選択し、それぞれ一意の要素を持つ配列として最初に定義された配列のパスの最初のコンポーネントのみを保存します(したがって重複はありません)。次に、配列の各要素を出力します。
find
を使用してリストを取得し、それを grep
にパイプすることができます。
(cd X && find . -type d -maxdepth 1 | sed -e 's,^./,,' | grep -E '^rf.*\.img$' )
サブシェルを使用して、X
内の名前だけを取得しました。それ以外の場合は、find
のパスを考慮する必要があります。
サブディレクトリが再帰的に必要な場合は、-maxdepth 1
オプションを省略できます。しかし、それはあなたが正規表現を調整しなければならないことを意味します、例えば、
(cd X && find . -type d | sed -e 's,^./,,' | grep -E '^(.*/)?rf.*\.img$' )
その場合、sedコマンドは冗長です(ただし無害です)。
grep
もls
も使用せず、find
を使用します。
find . -name 'rf*.img'
GNU find
には、ディレクトリのみを出力するオプションがあります(-printf "%h\n"
)しかし、あなたの場合、それはオプションではありません。
あなたは次のようなことをすることができます:
find . -name 'rf*.img' | sed 's:/[^/]*$::'
最初のディレクトリだけが必要な場合は、次のようになります。
find . -name 'rf*.img' -exec dirname {} \; | sed 's:./\([^/]*\).*:\1:'
Perl
とそのgrep
およびglob
を使用します。
#!/usr/bin/env Perl
use strict;
use warnings;
my @file_list = grep { /^rf.*\.img$/ } glob "*";
print join ( "\n", @file_list );
またはワンライナーとして:
Perl -e 'print join ( "\n", grep { /^rf.*\.img$/ } glob "*" )'
注-glob
はシェルスタイルのワイルドカード拡張を行うため、glob "*/*/name/*"
または同様のものを使用できます。任意の再帰深度が必要な場合は、代わりにFile::Find
を使用することをお勧めします。
#!/usr/bin/env Perl
use strict;
use warnings;
use File::Find;
sub print_match {
#Default match is against $_ which is filename.
#can match $File::Find::name for full name.
#or $File::Find::dir
print if /^rf.*\.img$/;
}
find ( \&print_match, "/path/to/search" );
再びワンライナーとして:
Perl -MFile::Find -e 'find ( sub { print if /^rf.*\.img$/ }, "/my/path/to/search" );'