路径斜杠后的Bash括号扩展


12

我正在尝试使用大括号扩展名将文件复制到相同的目录中。我正在使用bash 4.4.18。

这是我所做的:

cp ~/some/dir/{my-file-to-rename.bin, new-name-of-file.bin}

但是我得到这个错误:

cp: cannot stat '/home/xyz/some/dir/{my-file-to-rename.bin,': No such file or directory

甚至像这样简单的括号扩展也会给我同样的错误:

cp {my-file-to-rename.bin, new-name-of-file.bin}

我究竟做错了什么?

Answers:


29

括号扩展语法接受逗号,但不接受逗号后的空格。在许多编程语言中,逗号后的空格很常见,但这里并不常见。在Bash中,不带引号的空间的存在会阻止执行括号扩展。

删除空间,它将起作用:

cp ~/some/dir/{my-file-to-rename.bin,new-name-of-file.bin}

尽管完全不需要,但请注意,可以将尾部移动.bin到大括号之外:

cp ~/some/dir/{my-file-to-rename,new-name-of-file}.bin

如果要测试括号扩展的效果,可以使用echoprintf '%s ',或printf使用任何喜欢的格式字符串来执行此操作。(echo当我在Bash中时,我个人只是为此目的而使用,因为Bash的echo内置函数默认情况下不会扩展转义序列,因此相当适合检查实际运行的命令。)例如:

ek@Io:~$ echo cp ~/some/dir/{my-file-to-rename,new-name-of-file}.bin
cp /home/ek/some/dir/my-file-to-rename.bin /home/ek/some/dir/new-name-of-file.bin

23

string{foo, bar}不是大括号扩张;这是两个字string{foo,bar}。要使用花括号扩展,花括号必须在同一单词内。如果不需要,您必须删除多余的空间,或者如果需要则引用它:

$ printf "%s\n" aa{bb, cc}
aa{bb,
cc}
$ printf "%s\n" aa{bb,cc}
aabb
aacc
$ printf "%s\n" aa{bb," cc"}
aabb
aa cc

+1是明确的示例,谢谢。当我的名声足够时,我会投票。:)
nanangarsyad

关于“空壳词”,还有其他需要提及的地方。。.like shell如何知道在哪里拆分单词;)
Sergiy Kolodyazhnyy

-1

Bash会像对待其他空间一样对待该空间。作为IFS,内部字段分隔符。它用于扩展后的单词拆分,并使用read builtin命令将行拆分为单词。

外壳将IFS的每个字符视为定界符,并将其他扩展的结果拆分为这些字符上的单词。如果未设置IFS,或者其值正好是默认值,则将忽略,以及上一个扩展结果的开头和结尾处的序列,并且任何不在开头或结尾处的IFS字符序列都用于定界话。如果IFS的值不是默认值,则只要单词的开头和结尾都忽略了空格字符空格和制表符的序列,只要空格字符位于IFS值(IFS空格字符)中即可。IFS中不是IFS空格的任何字符,以及任何相邻的IFS空格字符,都将分隔字段。IFS空格字符序列也被视为定界符。如果IFS的值为null,
-bash(1)

通过插入未转义的定界符,然后您告诉bash您的命令和参数为:

  1. “ cp”
  2. “〜/ some / dir / {my-file-to-rename.bin,”
  3. “ new-name-of-file.bin}”

如果您有引号或转义符“ \”,则将具有:

  1. “ cp”
  2. “〜/ some / dir / {我的文件重命名.bin,\新文件名.bin}”

除非“ new-name-of-file.bin”是您想要的新文件名,否则这也不是您想要的。包含空间。当大括号扩展首先发生,然后波浪号扩展时,bash将执行:

  1. “ cp”
  2. “ /path/to/home/some/dir/my-file-to-rename.bin”
  3. “ /路径/到/ home / some / dir / \ new-name-of-file.bin”

只需删除空间即可解决所有问题。


5
多数情况下这很好,但是您似乎会说会发生分词cp ~/some/dir/{my-file-to-rename.bin, new-name-of-file.bin}IFS影响结果。也不是。在此,空间是标记化中的元字符步骤2)。有关何时发生分裂的信息,请参见3.5.7IFS=x然后尝试printf '[%s]\n' {a,b} printf '[%s]\n' {a, b} printf '[%s]\n' {a,xb} printf '[%s]\n' {a, xb}
伊莱亚·卡根
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.