我想根据包含空格的数据动态重命名文件
Name="Abc DEF"
Name1="GHI JKL"
mv /sample/pdf/noriginalName.pdf /sample/outputPdf/${NAME}${Name1}".pdf"
但它给了我一个错误,因为它之间遇到了空格。
我怎样才能做到这一点?
答案1
别担心,你不是第一个,也不会是最后一个被咬的人。这是有关 shell 的最常见问题,也是 shell 脚本中发现的大多数错误和安全漏洞的原因。这是由于早期 Unix 历史中 Bourne shell 和 Korn shell 的设计选择不当造成的。
在 Bourne shell 及其大多数后代(ksh、ash、pdksh、mksh、bash、dash、yash...)中,将变量不加引号是 split+glob 运算符。
最好的证明是:
$ var='*.txt,.*'
$ IFS=',' # default is space tab and newline
$ printf '<%s>\n' $var
<file.txt>
<.>
<..>
shell 已$var
按,
字符进行拆分,并在与相应模式匹配的文件列表中扩展了每个结果单词(在本例中包含通配符)。
这就是为什么,在类似 Bourne 的 shell 中(除了zsh
),你必须总是引用你的变量(除非你确实想要分裂和/或全局)
$ printf '<%s>\n' "$var"
<*.txt:.*>
所以在你的情况下:
mv /sample/pdf/noriginalName.pdf "/sample/outputPdf/${NAME}${Name1}.pdf"
或者:
mv /sample/pdf/noriginalName.pdf /sample/outputPdf/"${NAME}${Name1}".pdf
(只要变量被引用,引号放在哪里并不重要)。
您只能通过以下方式禁用拆分:
IFS=
您只能通过以下方式禁用通配符:
set -f # affects all globbing, not only the one done upon variable expansion.
和:
IFS=; set -f
您将获得与参数扩展相同的行为zsh
,没有通配符,没有分割。但您仍然需要引用您的变量
cmd "$var"
如果你想cmd
通过一当为空或未设置时为空参数$var
(与不根本没有争论)。一个典型的例子是,[ -n "$var" ]
如果您不引用$var
,则测试将始终为真,因为何时$var
为空,则解析为[ -n ]
而不是[ -n '' ]
。
在 中zsh
,通配符和拆分不会在变量扩展时隐式完成(除非在sh
或ksh
仿真模式下)。您必须使用特定的扩展运算符显式请求它:$=var
用于分词,$~var
用于通配(或${~var}
;$~=var
两者)。
其他不存在此类问题的 shell 是fish
、 和rc
及其后代 ( es
, akanga
)。
在(t)csh
:
cmd "$var"
$var
有帮助,但还不够,因为如果包含换行符,它不起作用。在那里,你需要:
cmd $var:q
答案2
您必须引用整个文件名:
mv /sample/pdf/noriginalName.pdf "/sample/outputPdf/${NAME}${Name1}.pdf"
使用双引号阻止bash
和其他类似 Bourne 的 shell(除了zsh
)执行场分裂变量扩展后。