次の問題があります:
ディレクトリには、、およびのExample1
3 つのファイルがあります。Example1
Things
Pictures
ディレクトリには、、およびのExample2
3 つのファイルがあります。Example2
Example3
Pictures
ディレクトリ名に一致するファイルのみを表示するリストが必要です。これは、Example1
およびですExample2
。diff、find、locate、ls などを試しましたが、何も達成できませんでした。
答え1
バックリファレンスを使用した正規表現で、格納ディレクトリと同じ名前のファイル名を簡単に一致させることができます。これらは、what/ever/something/something
2 つのsomething
部分が同一でスラッシュを含まない形式のファイル名です。BRE 正規表現構文では、[^/]*
スラッシュを含まない任意の文字列と一致し、\(/[^/]*\)
スラッシュの後に任意の数のスラッシュ以外の文字が続く文字列と一致し、全体をグループにし、\1
最初のグループに一致する同じテキストと一致します。したがって、\(/[^/]*\)\1
同じ名前の 2 つのパス セグメントと一致します。.*
先頭に追加すると、前のディレクトリ コンポーネントと一致します。
GNU find、FreeBSD find、macOS find など、以下find
をサポートするものを使用する場合-regex
:
find . -regex '.*\(/[^/]*\)\1'
答え2
通常、ディレクトリの数はファイルよりも少ないため、すべてのディレクトリを検索し、必要なファイル名が含まれているかどうかをテストしてみましょう。
find . -type d -exec sh -c '
for dirpath do
filepath="$dirpath/${dirpath##*/}"
[ -f "$filepath" ] && printf "%s\n" "$filepath"
done' sh {} +
これにより、ファイルと同じ名前を持つディレクトリにあるすべての通常ファイル (および通常ファイルへのシンボリック リンク) のパス名が出力されます。
テストは、いくつかのディレクトリ パス名を引数として取得する短いインラインsh -c
スクリプトで実行されます。各ディレクトリ パス名を反復処理し、探している名前のファイル パス名を構築します。${dirpath##*/}
コード内の は に置き換えることができます$(basename "$dirpath")
。
与えられたディレクトリ構造の例の場合、これは次のように出力されます。
./Example1/Example1
./Example2/Example2
ただテストするだけ任意の名前通常のファイルだけでなく、-f
テストをテストに変更します-e
。
答え3
使用find -exec
:
find . -type f \
-exec sh -c '[ "$(basename "$1")" = "$(basename "$(dirname "$1")")" ]' find-sh {} \; \
-print
は、内部-print
の結果がtrue の場合にのみ実行されます。[ ... ]
-exec sh -c '...'
出力:
./Example1/Example1
./Example2/Example2