哪些字符需要在没有引号的文件中转义?

jcu*_*bic 18 shell bash filenames quoting

我有基于浏览器的 shell/终端来执行 bash 命令,我正在转义空格,但事实证明括号也需要转义。对于不在引号中的文件名,还需要对哪些其他字符进行转义?

Gil*_*il' 34

简单的解决方案是'在开头放一个单引号 ( ),在结尾放另一个单引号,然后用'4 个字符的序列替换文件名中的每个字符'\''。所有字符在单引号字符串中都失去了它们的特殊含义,除了'它自己标记字符串的结尾。该序列'\''结束单引号文字,紧跟在单引号后面,并打开一个新的单引号文字。因此文件名

This file's name has some weird characters!
Will you manage to escape them?
Run Code Online (Sandbox Code Playgroud)

可以引用如下:

somecommand 'This file'\''s name has some weird characters!
Will you manage to escape them?'
Run Code Online (Sandbox Code Playgroud)

双引号有更复杂的转义规则,!如果历史替换被激活,不允许你包含感叹号,所以我不会进一步考虑它们。

另一种方法是用反斜杠保护字符。这适用于除换行符以外的每个字符;对于换行符,将其放在单引号(或双引号)内是唯一的解决方案。如果您想尽量减少反斜杠的数量以将引用的名称呈现给用户,您可以将其限制在需要反斜杠的地方;但是,您省略的反斜杠越多,您就越有可能忘记需要的反斜杠。字母、数字和非 ASCII 字符总是可以的¹。不确定时引用空格和标点符号。

对于典型的 shell(ksh、bash 或 zsh),您至少在某些情况下需要引用以下字符。

  • 空格(空格、制表符、换行符——记住换行符不能用反斜杠引用)。
  • ! ——历史扩展。
  • " — shell 语法。
  • #— 以空格开头的注释开始;zsh 通配符。
  • $ — shell 语法。
  • & — shell 语法。
  • ' — shell 语法。
  • (— 甚至在一个词的中间:ksh 扩展的 globs(在 bash 和 zsh 中也可用);zsh 通配符。
  • )(见(
  • * — sh 通配符。
  • , — 仅在大括号内扩展。
  • ; — shell 语法。
  • < — shell 语法。
  • = — 在 zsh 中,当它位于文件名的开头时(使用 PATH 查找的文件名扩展)。
  • > — shell 语法。
  • ? — sh 通配符。
  • [ — sh 通配符。
  • \ — shell 语法。
  • ] - 你可以不加引号。
  • ^——历史扩展;zsh 通配符。
  • ` — shell 语法。
  • { — 支撑扩展。
  • | — shell 语法。
  • } — 需要在 zsh 中转义,当没有匹配的左括号时,其他 shell 会更宽松。
  • ~— 位于文件名开头时的主目录扩展;zsh 通配符;当它是最后一个字符时总是安全的。

有时可能需要对更多字符进行特殊处理:

  • -对 shell 来说并不特殊,但是当它位于命令参数的开头时,它表示一个选项。它不能用引号保护,因为特殊处理是在命令中,而不是在 shell 中。为了保护以 开头的文件名-,您可以将./其放在它之前 - 这样它仍然是同一个文件,但参数不再以 开头-
  • .本身并不特殊,但*默认情况下点文件被排除在globs之外。
  • :对shell 来说并不是特别的,但有些命令会专门解析它,例如指示远程文件( hostname:filename)。请查阅该命令的文档以了解如何处理包含冒号的文件名。

¹除非用户配置了备用历史扩展字符。一些 shell 允许这样做。这是使用单引号而不是反斜杠的另一个原因。