不足している -exec 検索を使用してディレクトリ権限を繰り返し設定するにはどうすればよいですか?

不足している -exec 検索を使用してディレクトリ権限を繰り返し設定するにはどうすればよいですか?

find私のQnap NASにパラメータがないコマンドがあるので、-exec何かをパイプする必要があります。シェルは次のとおりです。GNU bash、バージョン3.2.57(2)-release-(arm-unknown-linux-gnueabihf)

現在のディレクトリのすべてのサブディレクトリ(ファイルではない)にsetgidビットを設定しようとしています。

これはうまくいきません:

find . -type d | xargs chmod g+s $1

などを"$1"使っても動作しません。両方とも、スペースを含むディレクトリ名が複数の引数として渡されていることを示します(どの引数がサポートされているかについての標準のヘルプメッセージを印刷します)。"$(1)"$("1")chmod

xargs必ず必要でなければ使用しません。長い名前はまだ息が詰まっているようではありませんか?

以下とそのバリエーションは機能しません。

find . -type d | chmod g+s

find . -type d | chmod g+s "$1"

awk引用符を使用または挿入することについて考えてみましたが、sedこれを行うより簡単な方法があると考える必要があります。人々は以前に何をしましたか-exec? (悲しいことに、私はおそらくこの事実を1995年頃に知っていたでしょう。しかし、長い間忘れていました。)

PS:これらの各ディレクトリ名には、Unicode文字、記号?などが含まれます。もともとはかなり許容可能なmacOSから来ました。つまり、?すべてのインスタンスを Unicode 文字などで置き換える必要があり、Windows はこれらの文字によって問題を経験しません。ただし、これもfind残りのバージョンが必要ですfind

答え1

出力は、改行で区切られたファイル名をエクスポートします。1 。findこれは目的の形式ではなく、目的の形式を生成しません。入力をスペースで区切られた項目に解析し、それを引用に使用します。一部のバージョンでは改行で区切られた入力を使用できますが、標準オプションが不足している場合はそうすることをお勧めします。xargsfindxargs\'"xargsfindxargs

find . -type d | xargs chmod g+sディレクトリ名にスペースやスペースが含まれていない限り、\'"no $1:これはシェルには意味がありますが、出力を解析してfind供給するためにシェルは関与しませchmodxargs

findhas-print0xargshas の場合、-0これらのオプションを使用して、任意のファイル名に対して機能する null で区切られたファイル名を渡すことができます。

find . -type d -print0 | xargs -0 chmod g+s

xargs標準オプションをサポートしている場合は、-Iそれを使用して各行をスペースで区切られた引用符付き文字列ではなく項目として処理するように指示できます。これはスペースを処理できますが、\"'改行は処理できません。

find . -type d | xargs -I {} chmod g+s {}

代わりに、シェルを使用して行を繰り返すことができますxargs。これは、改行文字を含まないすべてのファイル名に対して機能します。

find . -type d | while IFS= read -r line; do chmod g+s "$line"; done

どちらのソリューションも改行文字を含まないファイル名でのみ機能します。 with filenames include newlines の出力は、find解析するのが難しい場合を除いてあいまいです。複数のスラッシュが自発的に表示されないため、ナビゲートしたいディレクトリのパスを入力すると、出力がfindそれを認識できます。//以下は、この事実を使用して出力をfind入力形式でxargs

chars=$(printf '\t "'\\\')
{ find .//. -type d; echo .// } | LC_ALL=C sed -n '
s/['"$chars"']/\\&/g
/^\.\/\// {
x
s/\n/\\&/g
p
b
}
H' | LC_ALL=C xargs chmod g+s

1 より正確に言うと:改行で終了します(姓の後に改行があります)。

答え2

bashを使用して再帰を直接実行できます。それは次のとおりです。

shopt -s nullglob dotglob
recurse_chmod () (
  cd "$1"
  for d in ./*/
  do
    if [ -L "$d" ]; then continue; fi
    chmod g+s "$d"
    recurse_chmod "$d"
  done
)
recurse_chmod .

答え3

xargsに\ 0を区切り文字として使用するように指示できます。find . -type d -print0 | xargs -0 chmod g+s

または

find . -type d | xargs -I{} -d '\n' chmod g+s "{}"。区切り文字として \n を使用します。

関連情報