在 Bash 中,我们应该将文件名放在引号还是双引号中?标准是什么?

在 Bash 中,我们应该将文件名放在引号还是双引号中?标准是什么?

在 Bash 中,我们应该将文件名放在引号还是双引号中?标准是什么?

SRC=file

或者

SRC='file'

或者

SRC="file"

答案1

关于变量赋值需要注意的一点是,它们在 shell 语法中有点特殊。根据 Bash 文档,3.7.1 简单命令扩展

每个变量赋值中' ' 后面的文本=在分配给变量之前都会经过波浪符号扩展、参数扩展、命令替换、算术扩展和引号删除。

不过,一般来说,token 也会经历字段拆分和文件名扩展(参见3.5 Shell 扩展), 但这些不是在变量赋值期间执行的

这意味着未引用 $foo下列情况,将区别对待:

some-command $foo
bar=$foo

假设foo='/* a b c */'. (* a b c *是目录的完全有效名称,因此/* a b c */也是目录的完全有效路径。)对于some-command $foo,它首先变得就像您写道:

some-command /* a b c */

然后由 shell 扩展为如下内容:

some-command /bin /boot ... a b c dir1/ dir2/ ...

但对于bar=$foo,情况并非如此。不会进行字段拆分或文件名扩展,它将保持原样 -bar将具有值/* a b c */。但是,如果您随后执行some-other-command $bar,那么它将进行字段拆分和文件名扩展。

不过,在这两种情况下,引用"$foo"都会有相同的行为:

some-command "$foo" # no field splitting, no filename expansion
bar="$foo"          # equivalent to bar=$foo

一些经验法则:

  1. 如果您的值具有 shell 元字符,那么您必须至少引用这些元字符。元字符是:

    不加引号时用于分隔单词的字符。元字符是 spacetabnewline或以下字符之一:' |'、' &'、' ;'、' ('、' )'、' <' 或 ' >'。

  2. 如果值有!,并且启用了历史扩展(通常在交互式 shell 中是这种情况),则需要至少引用!using单引号或反斜杠。双引号不够。

  3. 如果值有一个~,并且你希望波浪符号扩展发生,那么“波浪号前缀” 必须不加引号(所以~/在 中"/some/path":~/"bar",或~user/在 中~user/".config/app",等等)。这使得可以将波浪号扩展与包含空格等的路径混合使用(所以~user/"some path (with metacharacters)")。

  4. 如果值具有参数扩展($foo,,${foo}等等),或者命令替换($(bar),或`foo`),或者算术扩展($((a+b))),或者类似于这些的内容,则:

    1. 如果不想执行扩展,请用单引号将它们括起来。您也可以使用反斜杠,但仅仅$在 中进行转义是不够的$(,因为(如上所述, 是元字符,也需要用引号引起来。
    2. 如果您希望扩展它们,则可以不引用它们,或者您可以使用双引号。
  5. 如果值中包含过程替换(>(...)<(...)),则仅当替换未加引号时才会执行。


数组与常规赋值不同。通常,(...)for内部的部分a=(...)会像命令行中其他任何地方一样进行扩展,因此会执行字段拆分和文件名扩展。这样就可以执行如下操作:

set -f
IFS=:
path=($PATH)

并将条目$PATH作为数组中的单独项目获取path

答案2

没有“标准”Bash 参考手册

变量(Shell 参数)

可以通过以下形式的语句来分配变量

name=[value]

引用

引号用于删除某些字符或单词对 shell 的特殊含义。引号可用于禁用对特殊字符的特殊处理、防止保留字被识别为保留字以及防止参数扩展。

在服务器系统上,默认文件名通常是标准字母数字字符,不包含任何特殊字符,并且应该引用一般来说不需要(尽管有例外可能申请)。

但是在桌面系统上,文件名包含空格和其他特殊字符的情况更常见,然后路径应该用引号引起来 - 这通常被认为是“安全路线”。

如果引用,请使用符合您需求的引号:单引号将按字面意思处理每个字符,而双引号仍将$`\视为!特殊字符。

但是引用的标准与分配变量的语法是分开的,因此它完全取决于变量的上下文(在本例中是文件名)。

答案3

无引号示例:

filePath=Documents Folder 2
echo "$filePath"

这将呼应文件
第一个空格后的所有内容都将丢失。您需要使用引号来保留空格。不使用引号仅适用于单个单词,但一般来说这不是一个好的做法。无论如何,最好使用引号。

双引号示例:

filePath="$HOME/Documents"
echo "$filePath"

这将呼应/home/用户名/Documents

单引号示例:

filePath='$HOME/Documents'
echo "$filePath" 

这将呼应$HOME/文档

如果希望系统按原样使用字符,则使用单引号。
如果希望系统处理变量或其他特殊用途,则使用双引号。

答案4

两者都可以工作,尽管略有不同。最大的区别在于,在单引号之间,大多数 shell 扩展(通配符、变量、命令替换等)都不会发生,因此如果您的文件名包含变量,例如:

$HOME/Documents/myfile.txt

如果您将其放在“单引号”中,那么无论文件名发送到哪个命令/程序,它都会被视为以文字 $ 字符开头,后跟“HOME”。使用“双引号”允许扩展变量名(因此上面的 $HOME 将替换为您的实际主目录),但不能使用通配符,即 * ? [ ] 等。转义空格和其他“分隔符”字符,或在使用通配符之前关闭(单引号或双引号)可使它们正常工作。

另一方面,如果您没有将文件名或应该包含文件名的变量放在引号中,那么包含空格或制表符的任何内容都会被分成几个参数,这通常不是您想要的。

相关内容