如何使用缺少 -exec 的 find 递归设置目录权限?

如何使用缺少 -exec 的 find 递归设置目录权限?

find我的 Qnap NAS 被一个缺少参数的命令所困扰-exec,所以我必须通过管道传输某些内容。 shell 是: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"

我考虑过使用awksed注入引号,但我必须认为有一种更简单的方法可以做到这一点。人们之前做了什么-exec? (可悲的是,我可能在 1995 年左右就知道了,但早已忘记了。)

PS:这些目录名称中的各种都会包含Unicode字符、符号?等。它们最初来自macOS,这是相当宽松的。也就是说,我可能应该?用 Unicode 字符之类的东西替换所有实例,这样 Windows 就不会因为它们而卡住。但这也需要find对这个残件版本的find.

答案1

的输出发出由换行符1find分隔的文件名。这不是想要的格式,也无法生成想要的格式:它将其输入解析为空格分隔的项目,并用于引用。某些版本可以采用换行符分隔的输入,但如果您缺乏标准选项,您也可能会这样做。xargsfindxargs\'"xargsfindxargs

find . -type d | xargs chmod g+s只要您的目录名称不包含空格或\'".请注意,没有$1: 这对 shell 有意义,但没有 shell 参与解析 的输出find并将其提供给chmod, only xargs

如果您的findhas-print0xargshas -0,您可以使用这些选项来传递空分隔的文件名,这适用于任意文件名。

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

如果您xargs支持标准选项-I,您可以使用它来指示它将每一行作为一个项目来处理,而不是用空格分隔的带引号的字符串。这可以处理空格,但不能处理\"'换行符。

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

您可以使用 shell 来循环行而不是xargs.这适用于任何不包含换行符的文件名。

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

这两种解决方案仅适用于不包含换行符的文件名。 with filenames contains 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 作为分隔符。

相关内容