我试图在 Bash 中为路径转义空格字符,但使用反斜杠或引号都不起作用。
.sh 脚本:
ROOT="/home/hogar/Documents/files/"
FILE=${ROOT}"bdd.encrypted"
DESTINATION="/home/hogar/Ubuntu\ One/folder"
mv ${FILE} ${DESTINATION}
Run Code Online (Sandbox Code Playgroud)
执行脚本 ( ./file
) 后,结果如下:
mv: target 'One/folder' is not a directory
Run Code Online (Sandbox Code Playgroud)
为什么mv
命令会拆分字符串,我该如何阻止这种情况发生?
Bra*_*iam 93
您正在扩展 DESTINATION 变量,如果您echo
这样做,您将得到:
echo ${DESTINATION}
/home/hogar/Ubuntu\ One/folder
Run Code Online (Sandbox Code Playgroud)
但mv
不明白这一点:
mv ${FILE} ${DESTINATION}
mv: cannot move '/home/hogar/Documents/files/bdd.encrypted' to '/home/hogar/Ubuntu\\ One/folder': No such file or directory
Run Code Online (Sandbox Code Playgroud)
(出于某种原因,我的 mv 更冗长)
为了防止这种情况,您应该使用引号:
mv "${FILE}" "${DESTINATION}"
Run Code Online (Sandbox Code Playgroud)
如果您不需要扩展(因为您之前已经扩展过),只需使用"$..."
就足够了:
mv "$FILE" "$DESTINATION"
Run Code Online (Sandbox Code Playgroud)
小智 29
您准备变量的步骤“足够接近”并且会起作用,但它确实显示出理解上的弱点(这就是您发布的原因!)
对 DESTINATION 的分配只需是以下两个之一:
DESTINATION="/home/hogar/Ubuntu One/folder"
Run Code Online (Sandbox Code Playgroud)
或者
DESTINATION=/home/hogar/Ubuntu\ One/folder
Run Code Online (Sandbox Code Playgroud)
双引号打开引用(一种具有某种魔力的形式),反斜杠能够引用它后面的单个字符。我个人认为使用双引号的形式更可取,因为它在视觉上更好。
顺便说一句,出于类似的原因,我会进行 FILE 分配,例如:
FILE="${ROOT}bdd.encrypted"
Run Code Online (Sandbox Code Playgroud)
这显示了使用${NAME}
而不是简单的非常罕见的场合$NAME
- 将变量名称与后面的任何字母分开。事实上,如果你在 ROOT 的定义上没有尾随 /,我会写
FILE="$ROOT/bdd.encrypted"
Run Code Online (Sandbox Code Playgroud)
这看起来更好。它也会偶尔给你带来我不会介绍的好处;让我们只是说根据我的经验,尾部斜杠往往更不受欢迎而不是受欢迎,而且绝对不需要它们。(当涉及到符号链接时,它确实会产生影响,但对于这个已经很大的答案来说,这绝对是太多的细节)。
你的问题的症结实际上发生在mv命令,它应该写成
mv "$FILE" "$DESTINATION"
Run Code Online (Sandbox Code Playgroud)
因为现在,您永远不知道表示路径的变量何时会包含空格。再次注意避免使用大括号进行简单的变量扩展。
出现问题的原因是 shell 用于构建命令行的过程。如果你仔细阅读 shell 手册,它基本上说变量(和其他一些东西)被扩展然后它去寻找空间。当然,在这个过程中还有一些更复杂的,但这是你的问题的要点。
还有一点这是相关的,非常值得了解一下:之间的区别$*
,$@
,"$*"
和"$@"
。那我来谈谈吧!
如果您有一个可以调用的 shell 脚本:
foo -x "attached is the software" "please read the accompanying manual"
Run Code Online (Sandbox Code Playgroud)
然后foo
将看到-x
的$1
,和两个字符串作为$2
和$3
(你应该访问的"$2"
和"$3"
显而易见的原因)。但是,如果您想将整个参数集传递给另一个脚本,以下内容将在所有空间上遭受可怕的分裂:
bar $*
Run Code Online (Sandbox Code Playgroud)
和以下(这是非常原始的 Bourn shell 的 0.X 版本中的唯一方法)将导致所有参数作为单个字符串传递(也是错误的)
bar "$*"
Run Code Online (Sandbox Code Playgroud)
因此添加了以下语法作为一个非常特殊的神奇案例:
bar "$@"
Run Code Online (Sandbox Code Playgroud)
它故意将单个成员$*
引用为完整的引用字符串,但将它们分开。现在每个人都是赢家。
尝试$@
不使用时的其他效果有点有趣,"$@"
但您很快就会发现它实际上并不那么有趣......它只是解决一个主要问题的特例。
所有支持数组的现代 shell 在特殊情况下也使用 @:
${arr[*]}
"${arr[*]}"
"${arr[@]}"
Run Code Online (Sandbox Code Playgroud)
其中第一个将在所有空格上拆分,导致不可预测数量的单独单词,第二个将在一个字符串中生成所有数组成员,第三个将非常好地将每个数组成员作为单独的完整引用字符串提供。
享受!
dai*_*isy 14
是的,当您将值分配给时,您转义了空间$DESTINATION
,
但是当你用 mv 命令使用它时,你没有
mv ${FILE} ${DESTINATION}
Run Code Online (Sandbox Code Playgroud)
改用这个:
mv "${FILE}" "${DESTINATION}"
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
236629 次 |
最近记录: |