現在のディレクトリにあるすべてのファイルを再帰的に展開するものは何ですか?


91

**/*.ext一致するすべてのサブディレクトリのすべてのファイルに展開することはわかってい*.extますが、現在のディレクトリにあるそのようなすべてのファイルを含む同様の展開とは何ですか?


4
私のbashは処理しません**/*.ext。それはあなたのために機能しますか?
タンジェンス2009年

@tangens globstarDennisの回答に従ってオプションを有効にする必要があります。
ケノーブ2015

回答:


110

これはBash 4で機能します。

ls -l {,**/}*.ext

ダブルアスタリスクのグロブが機能するためには、globstarオプションを設定する必要があります(デフォルト:オン):

shopt -s globstar

からman bash

    グロブスター
                  設定されている場合、ファイル名展開で使用されるパターン**
                  テキストはファイルと0個以上のディレクトリに一致し、
                  サブディレクトリ。パターンの後に/が続く場合は、
                  ディレクトリとサブディレクトリが一致しています。

今は、globstarの処理にバグがあったのではないかと思っls **/*.extています。これは、単に使用すると正しい結果が得られるためです。

とにかく、私はkenorbがVLCリポジトリを使用して行った分析を見て、その分析にいくつかの問題を見つけました。

findコマンドの出力との比較は、指定-type fに他のファイルタイプ(特にディレクトリ)が含まれておらず、lsリストされているコマンドにも含まれている可能性があるため、無効です。また、リストされたコマンドの1つ(ls -1 {,**/}*.*上記のものに基づいているように見える)は、サブディレクトリにあるファイルのドット含む名前のみを出力します。OPの質問と私の答えには、特定の拡張子を持つファイルが求められているため、ドットが含まれています。

ただし、最も重要なのはls、globstarパターンを使用したコマンドを使用する特別な問題があることです**。パターンが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 **と、それらのエントリのリストが出力されます。したがって、基本的にはがls A続くls A/ABため、A/AB2回表示されます。また、ls各サブディレクトリの出力を個別に設定します。

...
<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は、./からの出力の各行の先頭を削除していましたfindfind通常はソートされておらず、Bashのグロブの展開はすでにソートされているため、出力をソートしました。ご覧のとおり、からの唯一の出力diffは、による現在のディレクトリ.出力findでした。私が行っls ** | wc -lたとき、出力はほぼ2倍の行数でした。


5
私はUbuntuとCygwinをテストしましたglobstarが、デフォルトになっていますoff
Steven Penny

12
ベストアンサー!**/*.extでも十分だと思います。また、でない限り、隠しファイルはありませんshopt -s dotglob
gniourf_gniourf 2013

2
無効にするにはglobstarshopt -u globstar
kenorb

4
@gniourf_gniourf質問では、実際には現在のディレクトリを具体的に含めるように求められているので、いいえ、それだけで**/*.extは十分ではありません
msciwoj

2
@dotnetCarpenter:MacOSに同梱されているBashのバージョンは3.2で、ご存じのとおり、globstarをサポートしていません。二重アスタリスクは、単一アスタリスクと同じように扱われます。GlobstarはBash 4.0で導入されました。
追って通知があるまで一時停止。

13

このwilは、現在のディレクトリと '.ext'で終わるサブディレクトリにあるすべてのファイルを出力します。

find . -name '*.ext' -print

この答えは、OPが要求する「拡張」を厳密に満たすものではありませんが、望ましい結果をもたらす可能性が最も高くなります。
追って通知があるまで一時停止。

7

次を使用**/*.*して、すべてのファイルを再帰的に含めることができます(有効にする方法:)shopt -s globstar

他のバリエーションのテストとその動作を以下で確認してください。


サンプルVLCリポジトリフォルダー内の3472ファイルを含むテストフォルダー:

(につきとしてカウント3472の合計ファイル:find . -type f | wc -l

  • ls -1 **/*.* -3338を返します
  • ls -1 {,**/}*.*-3341を返します(Dennisの提案に従います)
  • ls -1 {,**/}* -8265を返します
  • ls -1 **/*-隠しファイルを除いて7817を返します(Dennisの提案による)
  • ls -1 **/{.[^.],}*-7869を返します(Dennisの提案に従います)
  • ls -1 {,**/}.?* -15855を返します
  • ls -1 {,**/}.* -20321を返します

したがって、すべてのファイルを再帰的に一覧表示する最も近い方法は、gniourf-gniourfコメント(ファイルに適切な拡張子があるか、特定の拡張子を使用していると想定**/*.*)の最初の例()であると思います。 :

$ diff -u <(ls -1 {,**/}*.*) <(ls -1 **/*.*)
--- /dev/fd/63  2015-04-19 15:25:07.000000000 +0100
+++ /dev/fd/62  2015-04-19 15:25:07.000000000 +0100
@@ -1,6 +1,4 @@
 COPYING.LIB
-COPYING.LIB
-Makefile.am
 Makefile.am
@@ -45,7 +43,6 @@
 compat/tdestroy.c
 compat/vasprintf.c
 configure.ac
-configure.ac

もう1つはさらに重複を生成します。


隠しファイルを含めるには、次を使用しますshopt -s dotglob(無効にするshopt -u dotglob)。mvまたはなどのコマンドに影響を与える可能性がありrm、誤って間違ったファイルを削除する可能性があるため、お勧めしません。


Mac端末とglobstarを有効にしたbashで、上記の解決策(**/*.*)は有益であり、最も効果的に機能しました。受け入れられた回答により、最上位ディレクトリにアイテムの重複が発生しました。私の作業パターンは次のとおりでした:"${path}"**/*.*
mummybot 2017年

nullglobやdotglobのような他のオプションでこれを試すのは興味深いでしょう
Wilf

3
$ find . -type f

現在のディレクトリにあるすべてのファイルが一覧表示されます。次に、-execを使用して、出力に対して他のコマンドを実行できます。

$find . -type f -exec grep "foo" {} \;

文字列「foo」の検索結果から各ファイルをgrepします。


11年経った今find . -type f、現在のディレクトリだけでなく、現在のディレクトリのルートを再帰的に適用する誰かが指摘する時かもしれません。
Roger Dahl

3

ブレース展開を使用して現在のディレクトリも含めるのはなぜですか?

./{*,**/*}.ext

ブレースの展開はグロブの展開の前に行われるため、古いバージョンのbashで効果的に必要な操作を実行でき、新しいバージョンのグロブスターを使用することはできません。

また、./グロブパターンにリーディングを含めることは、bashでの良い習慣と考えられています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.