サブフォルダ内の特定の拡張子を持つすべてのファイルに対してエレガントな方法でタスクを実行するには?

サブフォルダ内の特定の拡張子を持つすべてのファイルに対してエレガントな方法でタスクを実行するには?

現在の最良の選択は次のとおりです。

for i in $(find . -name *.jpg); do echo $i; done

問題:ファイル名のスペースを処理しません。

注:私は「tree」コマンドのようなグラフィカルな方法も好みます。

答え1

正式な方法は次のとおりです。

find . -name '*.jpg' -exec echo {} \;

\;(一度に+複数のファイルを渡して置き換えます)echo

または(GNU専用ですが、現在一部のBSDにも対応しています):

find . -name '*.jpg' -print0 | xargs -r0 echo

ジシュ語:

for i (**/*.jpg(D)) echo $i

答え2

より良い答えが提供されました。

ただし、あなたが提供したコードでスペースが唯一の問題ではないことに注意してください。タブ、改行、ワイルドカードも問題です。

そして

IFS='
'
set -f
for i in $(find . -name '*.jpg'); do echo "$i"; done

もしそうなら、改行だけが問題です。

答え3

あなたが言及したのは、人々がファイル名を読み取ろうとするときに直面する基本的な問題の1つです。時には、ファイルやフォルダの構造に関する知識が不足して誤解がある人がUNIXでは、すべてがファイルです。したがって、ファイル名はスペースを含む2つ以上の単語で構成される可能性があるため、スペースも処理する必要があることを理解していません。

解決策:したがって、よく知られている方法の1つは、次のことです。きれいな読書

ここでは、存在するすべてのファイルを読み取り、それを変数に保存し、次に必要な処理を実行するときにその変数を引用符で囲んで保持すると、ファイル名はスペースで保存されます。これはこれを行う基本的な方法の1つですが、ここの他の答えもうまく機能します。

スクリプト:

 find /path/to/files/ -iname "*jpg" | \
  while read I; do
   cp -v --parent "$I" /backup/dir/
  done

ここではファイルへのパスを提供してファイルを読み込み、私が読んでいる内容は変数Iに保存します。この変数は、後で処理するときに参照して正しく処理されるようにスペースを保存します。

これが何らかの方法で役立つことを願っています。

答え4

最新バージョンのbashでは、次のglobstarオプションを使用できます。

shopt -s globstar
for file in **/*.jpg ; do
    echo "$file"
done

単純な操作の場合は、ループを完全にスキップすることもできます。

echo **/*.jpg

関連情報