更改到调用脚本的目录的最安全(或最优雅或最短)的方法是什么?

更改到调用脚本的目录的最安全(或最优雅或最短)的方法是什么?

我想知道什么是安全的或 Unix 兼容的方法来更改到调用脚本的目录。

这两种方法甚至可以在包含空格和特殊字符的目录中工作,而无需使用引号。但在某些情况下这可能不起作用。或者有吗?

#!/bin/bash

cd $(dirname $0)
pwd
cd ${0%/*}
pwd

~/test 1"\ ü`\($$ ./cd.sh
/home/syss/test 1"\ ü`\($
/home/syss/test 1"\ ü`\($

答案1

请注意,这$0可能是相对路径,因此调用cd两次可能不起作用。除此之外,提取$0工程的目录部分最多案例。最多不等于全部。它可能失败的一些情况包括:

  • 该脚本不是通过运行其路径来调用的,而是通过在其上调用 shell 来调用,例如bash myscript(进行查找PATH)。
  • 脚本在执行期间会移动。

只要您记录您的脚本必须在没有恶作剧的情况下调用,就$0可以使用目录部分。

你需要小心一点;$0如果它是通过空条目找到的,或者PATH对于某些 shell,PATH..这个案例值得支持,这意味着您需要采取预防措施${0%/*}

这种dirname方法也不是完全简单的。命令替换会在最后吃掉换行符。使用这两种方法时,您需要注意字符串可以以 开头-并被解释为选项; pass--终止命令的选项列表。

case "$0" in
  */*) cd -- "${0%/*}";;
  *) cd -- "$0";;
esac

或者

cd -- "$(dirname -- "$0"; echo /)"

关于双引号,您问了错误的问题。"$0"是参数 的值0$00,不带引号,是在每个元素中的字符处分割的参数值IFS,然后解释为通配符模式并由匹配文件替换(如果有的话)(后一部分仅在通配符未关闭的情况下)。您的意思并不是说参数的值0在每个元素中的字符处分割IFS,然后解释为通配符模式并由匹配文件替换(如果有的话)(后一部分仅在通配符未关闭的情况下),是吗?你的意思是参数的值0。所以写下你的意思:"$0"

您的测试没有阻塞的唯一原因是您没有尝试使用有问题的名称,并且您使用特定的 shell 进行测试,该 shell 恰好可以修复此特定场景中的错误。对于像这样的目录名称foo bar,您最终会向命令传递两个参数foo和; bash 的命令将其解释为“更改为通过连接、空格和而获得的目录”,因此它恰好会重新构建正确的名称。不同的 shell 可能会将其解释为“抱怨虚假参数”、“更改到目录”或“更改到通过在当前工作目录中替换by获得的目录”。例如,使用 bash,如果名称包含两个连续空格,您的脚本将会失败。barcdcdfoobarfoofoobar

相关内容