2

bash スクリプトを開始していますが、空白のファイル名を処理できません。ここで私の問題に関する他の質問を検索しました。

SINGLE行で引用符で囲まれたファイル名を出力する方法は?

私のスクリプトでは、すべてのディレクトリを取得する必要があり、それぞれが何らかの作業を行っているために終了します。したがって、私のスクリプトのスケルトンは次のとおりです。

for directory in `find "$DIR" -type d`
do
# ... some work ...
done

このスクリプトは、空白のファイル名では機能しません。そこで、find を exec と組み合わせて使用​​してみました。これはエレガントで簡単な解決策のようですが、何も変わりませんでした。より正確には、私は試しました:

(I)  find "$DIR" -type d -exec echo -n '"{}" ' \;
(II) find "$DIR" -type d -exec echo -n '"{}" ' +

コマンド -exec を使用する前に、それについて何か読んだことがありますが、まだはっきりしていないことがあります。

  1. '"{}" ' \;
  2. '"{}" ' +
  3. 空白のファイル名に対してもスクリプトを修正するにはどうすればよいですか?
4

3 に答える 3

2

'"{}" ' \;

ファイル名ごとに、これは基本的に を実行 echo -n "\"filename\" "し、 のような一連の行を生成し"filename"ます。

ただし、bash はデータをシェル スクリプト コードとして解釈し始めないため、リテラルの引用符を追加しても役に立ちません。

の場合read foo; ls $foo、単に入力し$(rm /)てコマンドを実行することはできず、単に入力し"foo bar"てファイル名の分割を回避することもできません。データはコードではなくデータであり、シェル構文は尊重されません。

'"{}" ' +

+ファイル名のグループに対してコマンドを 1 回実行します (効率のため、一度に 1 つずつではなく)。置換が機能する方法により{} +、引数が削除され、一連のファイル名に置き換えられているため、 と同じです。

空白のファイル名に対してもスクリプトを修正するにはどうすればよいですか?

IFS変数を使用して、bash が分割に使用する文字を変更するだけで、95% のケースで機能させることができます。

IFS=$'\n'
for dir in $(find "$DIR" -type d)
do 
   echo "Directory: >> $dir <<"
done

これにより、すべての空白のデフォルトではなく、改行だけで bash が分割されます (これにより、コードの残りの部分で興味深い副作用が発生する可能性があるため、後で IFS の値を元に戻すことをお勧めします)。

ただし、ファイル名には改行を含めることもできます。最良のアプローチは、次を使用することです。

while IFS= read -d '' -r dir
do
    echo "Directory: >> $dir <<"
done < <(find "$DIR" -type d -print0)

これによりfind、ファイル名に含めることのできない NUL バイトで分割された出力ファイルが作成されます。

于 2013-04-02T00:42:31.360 に答える
1

これはあなたにとってよりうまくいくかもしれません:

while IFS= read -r adir ; do
    echo "Directory: $adir"
done < <(find "$DIR" -type d)
于 2013-04-01T22:36:49.013 に答える
1

私はこの形式を使用しており、正常に動作します:

find '/path/to/directories' -type d |\
  while read DIRNAME
  do
    echo "${DIRNAME}"
  done
于 2013-04-01T22:45:14.663 に答える