web-dev-qa-db-ja.com

サブフォルダー内の特定の拡張子を持つすべてのファイルに対してエレガントな方法でアクションを実行するにはどうすればよいですか?

私の現在の最善の策は:

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

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

注:「tree」コマンドなど、これを行うグラフィカルな方法も気に入っています。

19
Vorac

正規の方法は

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

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

または(GNU固有ですが、一部のBSDでも同様になっています):

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

zsh:

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

より良い答えはすでに与えられています。

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

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

次に、改行文字だけが問題になります。

2

あなたが述べたことは、人々がファイル名を読み取ろうとするときに直面する基本的な問題の1つです。時々、知識が限られていて、ファイルとフォルダの構造を誤解している人は、「NIXではすべてがファイルです」ということを忘れがちです。したがって、ファイル名はスペースを含む2つ以上の単語で構成できるため、スペースも処理する必要があることを理解していません。

Solution:したがって、これを行うためのよりよく知られている方法の1つは、clean readを実行することです。

ここでは、存在するすべてのファイルを読み取り、それらを変数に保持します。次に、目的の処理を実行するときに、スペースでファイル名を保持する引用符で変数を保持する必要があります。これは基本的な方法の1つですが、ここにいる他の人々によって提供される他の回答も同様に機能します。

SCRIPT:

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

ここでは、ファイルへのパスを指定してファイルを読み取っています。読み取っているものはすべて変数I内に保持しています。後で処理するときに、スペースを保持して正しく処理するために引用します。

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

1
The Dark Knight

単にfindおよびbashを使用します。

find . -name '*.jpg' -exec bash -c '
    echo "treating file $1 in bash, from path : ${1%/*}" 
' -- {} \;

この方法では、$1 bashでは、基本的なスクリプトのように、Niceパースペクティブを開いて高度な(またはそうでない)タスクを実行します。

より効率的な方法(すべてのファイルに対して新しいbashを開始する必要をなくすため):

find . -name '*.jpg' -exec bash -c 'for i do
    echo "treating file $i in bash, from path : ${i%/*}" 
  done' -- {} +
1
Gilles Quenot

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

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

単純なアクションの場合は、ループ全体をスキップすることもできます。

echo **/*.jpg
0
choroba