sys*_*yss 0 bash cd-command posix pwd
我想知道更改到调用脚本的目录的安全或 Unix 兼容方式是什么。
这两种方法甚至可以在包含空格和特殊字符的目录中工作,而无需使用引号。但是在某些情况下这可能不起作用。或者有吗?
#!/bin/bash
cd $(dirname $0)
pwd
cd ${0%/*}
pwd
~/test 1"\ ü`\($$ ./cd.sh
/home/syss/test 1"\ ü`\($
/home/syss/test 1"\ ü`\($
Run Code Online (Sandbox Code Playgroud)
请注意,这$0可能是相对路径,因此调用cd两次可能不起作用。除此之外$0,大多数情况下提取目录部分是有效的。大多数是不一样的一切。它可能失败的一些情况包括:
bash myscript(它进行PATH查找)。只要您记录必须在没有恶作剧的情况下调用您的脚本,就可以使用 的目录部分$0。
你需要小心一点;可能$0根本不包含斜杠,如果它是通过空PATH条目找到的,或者在某些 shell 中PATH找到.. 这个案例值得支持,这意味着您需要对${0%/*}.
这种dirname方法也不是完全直接的。命令替换在最后吃掉换行符。使用这两种方法,您需要注意字符串可以以开头-并被解释为选项;pass--终止命令的选项列表。
case "$0" in
*/*) cd -- "${0%/*}";;
*) cd -- "$0";;
esac
Run Code Online (Sandbox Code Playgroud)
或者
cd -- "$(dirname -- "$0"; echo /)"
Run Code Online (Sandbox Code Playgroud)
关于双引号,你问错了问题。"$0"是参数的值0。$0,未加引号,是0在IFS每个元素的字符处拆分的参数值,然后将其解释为 glob 模式并替换为匹配文件(如果有的话,后者仅在未关闭 globbing 的情况下)。你不是说参数的值0在IFS每个元素的字符处拆分,然后解释为 glob 模式并替换为匹配的文件(如果有的话,后者只有在 globbing 没有关闭的情况下),对吗?你的意思是参数的值0。所以写下你的意思:"$0"。
您的测试没有卡住的唯一原因是您没有尝试使用有问题的名称,而是使用特定的外壳进行测试,该外壳恰好可以修复您在此特定场景中的错误。使用类似 的目录名称foo bar,您最终会向命令传递两个参数foo和;bash 的命令将此解释为“更改到通过连接、空格和”获得的目录,因此它恰好重建了正确的名称。不同的 shell 可能会将其解释为“抱怨虚假参数”、“更改到目录”或“更改到通过在当前工作目录中替换而获得的目录”。例如,使用 bash,如果名称包含两个连续的空格,您的脚本就会失败。barcdcdfoobarfoofoobar