Linux程序只在必要时引用文件名?

Linux程序只在必要时引用文件名?

考虑拥有这些目录和文件:

$ tree /tmp/test
/tmp/test
├── dir
│   ├── file_normal
│   ├── file with "double quote
│   ├── file with 'single quote
│   ├── file with space
│   └── special!char
├── dir with space
│   ├── file_normal
│   ├── file with "double quote
│   ├── file with 'single quote
│   ├── file with space
│   └── special!char
├── file_normal
├── file with "double quote
├── file with 'single quote
├── file with space
└── special!char

ls添加单引号或双引号仅在必要时。注意dirfile_normal没有引用。

$ ls -1 /tmp/test
dir
'dir with space'
file_normal
'file with "double quote'
"file with 'single quote"
'file with space'
'special!char'

ls对单个文件执行相同的操作。

不必要时不要添加引号:

$ ls "file_normal"
file_normal
$ ( cd dir ; ls "$( realpath file_normal )" )
/tmp/test/dir/file_normal

仅在必要时添加引号:

$ ls "file with space"
'file with space'
$ ( cd 'dir with space' ; ls "$( realpath file_normal )" )
'/tmp/test/dir with space/file_normal'

通常不鼓励考虑ls在 shell 脚本程序中使用。有没有内置的Linux程序可以实现相同的功能:仅在必要时才向文件路径添加单引号或双引号?

答案1

是的:ls。只需使用它即可。与任何规则一样,“不要使用 ls”也会有有意义的例外情况。这是其中之一。首先你需要了解为什么ls不鼓励使用:

  • 它用于简单的 shell glob 完美完成工作的情况,并且通常比可以做得更好,ls因为 shell 会直接为您提供单独单词的路径,而无需解析 的ls输出。 (当你看到类似for i in $(ls *.xyz)而不是的东西时,这尤其令人恼火for i in *.xyz。)
  • 当尝试获取额外信息和文件名时,可变的列大小使其ls -l难以解析。使用statfind代替。
  • ls?可能会使输出中特殊字符的处理变得棘手(例如,某些字符被替换)。

在这种情况下:

  • 你显然已经有相关的路径,所以你不会误用ls它来获取glob就足够的地方
  • 您没有使用ls -l或尝试获取路径以外的任何信息
  • ls提供(但--quoting-style=shell-escape具体)的特殊输出

所以,只需使用类似的东西:

quoted_path=$(ls -d --quoting-style=shell-escape <some-path>)

只是一定要明白这不是标准。最近版本的 GNU ls 可以做到这一点,但 busybox ls 没有(AFAICT),因此并非所有 Linux 系统都会有它。


您还可以使用GNU 统计对于同样的事情,使用%N格式说明符:

  • %N– 如果是符号链接,则引用文件名并取消引用(见下文)
    [...]可以使用环境变量设置
    “ ”格式。如果未设置该环境变量,则默认值为“ ”。%NQUOTING_STYLEshell-escape-always

所以:

quoted_path=$(QUOTING_STYLE=shell-escape stat -c %N <some-path>)

for 的引用样式stat似乎与 for 相同ls(我敢打赌它们在内部使用相同的函数)。在这种情况下,主要的区别似乎是符号链接处理:stat如果您想按原样处理符号链接,则可能不是您想要使用的:

% QUOTING_STYLE=shell-escape stat -c %N bar$'\n'baz$'\t'xyz
'bar'$'\n''baz'$'\t''xyz' -> 'foo bar'
% ls --quoting-style=shell-escape bar$'\n'baz$'\t'xyz
'bar'$'\n''baz'$'\t''xyz'

其他选项:

  • Bash 参数扩展使用Q引号运算符:${foo@Q}将用引号打印变量的内容foo(但它似乎总是添加一些引号)
  • Bash 的printf格式%q说明符(虽然它似乎优先使用反斜杠而不是引号,但如果不需要则不会添加转义)

相关内容