5

for簡単な bashループを作成して、すべてのサブディレクトリのアクセス許可を変更しようとしています。

for dir in `find . -type d`; do chmod 755 "$dir"; done

ただし、存在しないディレクトリについて文句を言います。ループからディレクトリ名を出力するだけで( に置き換えchmod 755 "$dir"echo "$dir")、ディレクトリの名前にスペースが含まれていると問題が発生することがわかりました。何が起こるかというと、ループはすべての改行スペースforの結果を分割します。find

改行のみに従って結果を分割し、スペースを無視するようにしたいと思います。二重引用符は、文字列がchmod1 つの引数として到達することを確認する必要があります。分割を変更するにはどうすればよいですか?

4

3 に答える 3

7

この問題の通常の解決策は次のとおりです。

find ... -print0 | xargs -0 ...

この-print0引数により、出力ファイル名はヌルで終了し、xargs への-0/引数は、そのような形式を読み取るように指示します。-null

だからあなたの場合...

$ find . -type d -a -print0 | xargs -0 chmod 755

実際には、シェル ループはまったく必要ありません。

于 2013-02-22T17:40:32.610 に答える
4

ツールキットのその他のオプションを次に示します。ファイル/ディレクトリのグループに対して実行するコマンドが1つしかない場合はfind、直接実行できます。

find . -type d -exec chmod 755 {} +

コマンドが一度に 1 つのファイル/ディレクトリに対してしか機能しない場合は、アイテムごとに 1 回実行する\;代わりに使用します。+

find . -type d -exec chmod 755 {} \;

また、何か複雑なこと (つまり、いくつかのコマンド) を行う必要がある場合は、ループの安全なバージョンを作成できます。

while IFS= read -r -u3 -d $'\0' dir; do
    sudo chown gkudelis "$dir"
    chmod 755 "$dir"
    touch "$dir/.perms_reset"
done 3< <(find /tmp -type f -print0)

これは<(...)、パイプの代わりにプロセス置換 ( ) からのリダイレクトを使用して、サブシェルでのループの実行を回避することに注意してください。#!/bin/bashこれは bash のみの機能であるため、スクリプトはではなくで開始する必要があります#!/bin/sh。また、stdin ではなく fd 3 へのリダイレクトを行うため、ループ内の何かが stdin から読み取ろうとしても、混乱することはありません。また、ループ変数 ("$dir"この例では) へのすべての参照を二重引用符で囲み、その中のスペースを保護してください。詳細については、 BashFAQ #020を参照してください。

于 2013-02-22T20:13:27.493 に答える
1

代わりにこれを試してください ( builtinsbash --versionを使用し、 >= 4が必要です) :

shopt -s globstar
for dir in **/*/; do
    chmod 0755 "${dir%/}"
done
于 2013-02-22T17:39:32.610 に答える