使用 `find 转义文件名上的异常字符。-printf "%p \n"`

Jul*_*cea 4 find special-characters

来自此find命令的文件路径

find . -printf "%p \n"
Run Code Online (Sandbox Code Playgroud)

不要转义异常(空格、反斜杠、双引号...)字符。

-ls选项确实打印转义路径,但它只是将 的输出添加ls -dilsprintf.

我需要一个高效的命令,所以运行一个额外的命令ls并没有帮助,也没有打印出所有额外的字符。

有没有其他(优雅的)方法来输出转义路径find

ilk*_*chu 6

通常,您希望find -exec用于为所有文件名运行命令,或者find -print0将名称通过管道传递给某些可以读取由 nul 字节分隔的条目(如xargs -0)的命令。

如果你真的想要引用字符串,Bash 有几个选项可以做到这一点:

$ find -exec bash -c 'printf "%s\n" "${@@Q}"' sh {} +
'./single'\''quote'
'./space 1'
$'./new\nline'
'./double"quote'

$ find -exec bash -c 'printf "%q\n" "$@"' sh {} +
./single\'quote
./space\ 1
$'./new\nline'
./double\"quote
Run Code Online (Sandbox Code Playgroud)

这确实需要对 shell 进行额外调用,但可以使用一个 exec 处理多个文件名。


关于保存权限位(虽然不是 ACL),您可以执行以下操作(在 GNU find 中):

find -printf "%#m:%p\0" > files-and-modes
Run Code Online (Sandbox Code Playgroud)

这将输出与输入的权限,一个冒号,文件名和NULL字节,如:。它不会转义任何内容,而是会按原样打印文件名(除非输出到终端,在这种情况下至少换行符会被破坏。)0644:name with spaces\0

您可以使用 Perl 脚本读取结果:

perl -0 -ne '($m, $f) = split/:/, $_, 2; chmod oct($m), $f; ' < files-and-modes 
Run Code Online (Sandbox Code Playgroud)

或者几乎不使用 Bash,请参阅评论:

while IFS=: read -r -d '' mode file ; do
    # do something useful
    printf "<%s> <%s>\n" "$mode" "$file"
    chmod "$mode" "$file"
done < files-and-modes
Run Code Online (Sandbox Code Playgroud)

据我测试,这适用于换行符、引号、空格和冒号。请注意,我们需要使用除空格以外的其他内容作为分隔符,因为IFS=" "如果任何名称包含尾随空格,设置将删除它们。