我想根据包含空格的数据动态重命名文件
Name="Abc DEF"
Name1="GHI JKL"
mv /sample/pdf/noriginalName.pdf /sample/outputPdf/${NAME}${Name1}".pdf"
Run Code Online (Sandbox Code Playgroud)
但它给了我一个错误,因为它在两者之间遇到了空间。
我怎样才能做到这一点?
别担心,你不是第一个,也不会是最后一个被它咬到的。这是有关 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>
<.>
<..>
Run Code Online (Sandbox Code Playgroud)
外壳程序$var
在,
字符上进行了拆分,并在与相应模式匹配的文件列表中扩展了每个结果词(在本例中包含通配符)。
zsh
),您必须始终引用您的变量(除非您确实想要split和/或glob)$ printf '<%s>\n' "$var"
<*.txt:.*>
Run Code Online (Sandbox Code Playgroud)
所以在你的情况下:
mv /sample/pdf/noriginalName.pdf "/sample/outputPdf/${NAME}${Name1}.pdf"
Run Code Online (Sandbox Code Playgroud)
或者:
mv /sample/pdf/noriginalName.pdf /sample/outputPdf/"${NAME}${Name1}".pdf
Run Code Online (Sandbox Code Playgroud)
(只要引用了变量,您将引号放在哪里并不重要)。
您只能通过以下方式禁用拆分:
IFS=
Run Code Online (Sandbox Code Playgroud)
您只能通过以下方式禁用通配符:
set -f # affects all globbing, not only the one done upon variable expansion.
Run Code Online (Sandbox Code Playgroud)
和:
IFS=; set -f
Run Code Online (Sandbox Code Playgroud)
您将获得与zsh
参数扩展相同的行为,没有通配符,没有拆分。你仍然需要引用你的变量但是在
cmd "$var"
Run Code Online (Sandbox Code Playgroud)
如果您想在为空或未设置时cmd
传递一个空参数$var
(而不是根本没有参数)。一个典型的例子是[ -n "$var" ]
,如果您不引用$var
,则测试将始终为真,因为 when$var
为空,则解析为[ -n ]
而不是[ -n '' ]
。
在 中zsh
,globbing 和 splitting 不是在变量扩展时隐式完成的(除了 insh
或ksh
emulation 模式)。您必须使用特定的扩展运算符明确请求它:$=var
用于分词、$~var
用于通配符(或${~var}
;$~=var
用于两者)。
没有这种问题的其他 shell 是fish
,rc
和 及其后代 ( es
, akanga
)。
在(t)csh
:
cmd "$var"
Run Code Online (Sandbox Code Playgroud)
有帮助但还不够,因为如果$var
包含换行符就不起作用。在那里,您需要:
cmd $var:q
Run Code Online (Sandbox Code Playgroud)