子Shell中使用的"basename"返回"command not found"错误

9
当运行此脚本时:
#!/bin/sh -ex

if [[ $# -ne 1 ]]; then
  echo "./import-public-ssh-key.sh <absolute path to public key>"
  exit 1;
fi

PATH=$1
KEY=$(basename ${PATH})

我理解为:

./import-public-ssh-key.sh: line 9: basename: command not found

如果没有子Shell,basename 就可以工作:

$ basename /Users/mles/.ssh/id_rsa.pub
id_rsa.pub

为什么basename在子shell中无法工作?如果这跟我的Mac有关,那怎么办?

5
PATH 有特殊的意义。因此,您应该使用小写名称来命名自己的变量,以避免错误地覆盖更改 shell 或操作系统行为的变量。换句话说:path=$1 不会有任何风险。 - Charles Duffy
1
请参见http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html的第四段,该约定在POSIX中得到了确立。 - Charles Duffy
2
顺便提一下,“sh -e”是有争议的;它很容易引起比它预防的更多的错误,包括奇怪的上下文敏感错误,这些错误很难通过测试来避免。在决定使用它之前,请参见BashFAQ#105中的练习和不同实现之间的不兼容性列表https://www.in-ulm.de/~mascheck/various/set-e/。 - Charles Duffy
2
如果你想编写一个bash脚本,而不是sh脚本,那么请使用#!/bin/bash作为你的shebang,而不是#!/bin/sh。使用sh shebang不能保证你将拥有除POSIX shell语言规范中给出的语言特性之外的任何语言特性。 - Charles Duffy
1
此外 - 这是我最后的评论,我保证 - 你可以考虑养成通过 http://shellcheck.net/ 运行你的代码的习惯;在这种情况下,它可能会告诉你需要对传递给 basename 的参数中的扩展进行引用,以便正确处理包含空格的路径,或者当 IFS 被设置为包含可能存在于文件名中的字符时;花括号在这里没有任何区别,但引号可防止字符串分割和通配符扩展。 - Charles Duffy
显示剩余2条评论
1个回答

11

您重置了PATH。请不要这样做。Shell会搜索PATH中列出的所有目录,而您已更改了PATH,使得PATH不再包含包含basename的目录。


回答常见问题?嘘,嘘。 - Charles Duffy
1
好的,那个变量名真的很糟糕:P 感谢提示。 - mles

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接