**/*.ext一致するすべてのサブディレクトリ内のすべてのファイルに展開されることは知っていますが、現在のディレクトリ*.ext内のそのようなすべてのファイルも含む同様の展開とは何ですか?
5 に答える
これは Bash 4 で機能します。
ls -l {,**/}*.ext
二重アスタリスクのグロブを機能させるには、globstarオプションを設定する必要があります (デフォルト: オン):
shopt -s globstar
からman bash:
グロブスター
設定されている場合、ファイル名展開コンで使用されるパターン **
text は、ファイルおよび 0 個以上のディレクトリと一致し、
サブディレクトリ。パターンの後に / が続く場合のみ
ディレクトリとサブディレクトリが一致します。
globstar の処理にかつてバグがあったのではないかと考えているのですが、単純ls **/*.extに使用するだけで正しい結果が得られるようになりました。
とにかく、VLCリポジトリを使用してkenorbが行った分析を調べたところ、その分析とすぐ上の回答にいくつかの問題が見つかりました。
コマンドの出力との比較findは無効です。これは、指定-type fに他のファイル タイプ (特にディレクトリ) が含まれておらず、lsリストされているコマンドが含まれている可能性が高いためです。また、リストされているコマンドの1つls -1 {,**/}*.*-上記の私のものに基づいているようですが、サブディレクトリにあるファイルのドットを含む名前のみを出力します。探しているのは特定の拡張子を持つファイルであるため、OPの質問と私の答えにはドットが含まれています。
ただし、最も重要なことはls、 globstar pattern でコマンドを使用すると特別な問題が発生すること**です。Bash によってパターンが調査中のツリー内のすべてのファイル名 (およびディレクトリ名) に展開されるため、多くの重複が発生します。展開に続いて、lsコマンドはそれらのそれぞれと、ディレクトリの場合はその内容を一覧表示します。
例:
現在のディレクトリには、サブディレクトリAとその内容があります。
A
└── AB
└── ABC
├── ABC1
├── ABC2
└── ABCD
└── ABCD1
そのツリーで、**「AA/AB A/AB/ABC A/AB/ABC/ABC1 A/AB/ABC/ABC2 A/AB/ABC/ABCD A/AB/ABC/ABCD/ABCD1」に展開されます (7 エントリ) . これを行うecho **と、正確な出力が得られ、各エントリが 1 回表示されます。ただし、そうすると、それらの各エントリls **のリストが出力されます。したがって、基本的には, などが続くため、 2 回表示されます。また、各サブディレクトリの出力を別々に設定します。ls Als A/ABA/ABls
...
<blank line>
directory name:
content-item
content-item
したがって、使用するwc -lと、すべての空白行とディレクトリ名セクションの見出しがカウントされ、さらにカウントがずれます。
これは、解析lsすべきではないもう 1 つの理由です。
この詳細な分析の結果として、次の方法でファイルのツリーを反復処理する以外の状況では globstar パターンを使用しないことをお勧めします。
for entry in **
do
something "$entry"
done
最終的な比較として、手元にあった Bash ソース リポジトリを使用して、次のようにしました。
shopt -s globstar dotglob
diff <(echo ** | tr ' ' '\n') <(find . | sed 's|\./||' | sort)
0a1
> .
tr名前にスペースが含まれていないため、ここでのみ有効な改行にスペースを変更していました。からの出力の各行からsed先頭を削除していました。通常はソートされておらず、Bash のグロブ展開は既にソートされているため、出力をソートしました。ご覧のとおり、 からの唯一の出力は、によって出力された現在のディレクトリです。私が行ったとき、出力にはほぼ2倍の行がありました。./findfinddiff.findls ** | wc -l
これにより、現在のディレクトリとそのサブディレクトリ内の「.ext」で終わるすべてのファイルが出力されます。
find . -name '*.ext' -print
$ find . -type f
これにより、現在のディレクトリ内のすべてのファイルが一覧表示されます。次に、-execを使用して出力に対して他のコマンドを実行できます。
$find . -type f -exec grep "foo" {} \;
これにより、文字列「foo」の検索から各ファイルがgrepされます。