如何拆分 $0 变量以在 bash 中查找目录和相对路径?

pro*_*eek 10 bash parameter

$0 变量包含脚本的路径信息。

  • 如何将路径信息更改为绝对路径?我的意思是如何处理 ~, ., .. 或类似的?
  • 如何将路径信息拆分为目录和文件名?

我可以为此使用 python/perl,但如果可能,我想使用 bash。

Mic*_*zek 17

您不需要处理诸如 之类~的事情,shell 会为您完成。这就是为什么您可以传递~/filename给任何脚本或程序并且它可以工作的原因——所有这些程序都不处理~自己,您的 shell 将参数转换为/home/username/filename并将其传递给程序:

$ echo ~/filename
/home/mrozekma/filename
Run Code Online (Sandbox Code Playgroud)

如果您需要一个规范的文件名(一个不包含诸如 之类的内容..),请使用realpath(感谢Neil):

$ realpath ~/../filename
/home/filename
Run Code Online (Sandbox Code Playgroud)

至于将路径拆分为目录名和文件名,请使用dirnamebasename

$ dirname /foo/bar/baz
/foo/bar

$ basename /foo/bar/baz
baz
Run Code Online (Sandbox Code Playgroud)


ech*_*hox 5

使用迈克尔提到的 dirname 和 basename 应该是获得所需内容的最安全方法。

无论如何,如果您真的想使用“仅 bash 工具”来执行此操作,则可以使用参数替换:

echo `basename $PWD`        # Basename of current working directory.
echo "${PWD##*/}"           # Basename of current working directory.
echo
echo `basename $0`          # Name of script.
echo $0                     # Name of script.
echo "${0##*/}"             # Name of script.
echo
filename=test.data
echo "${filename##*.}"      # data
                            # Extension of filename.
Run Code Online (Sandbox Code Playgroud)

这个例子直接取自Advanced Bash Scripting Guide,值得一看。

解释很简单:

${var#Pattern} 从 $var 中删除 $Pattern 中与 $var 前端匹配的最短部分。${var##Pattern} 从 $var 中删除 $Pattern 中与 $var 前端匹配的最长部分。

将模式视为一些正则表达式,将#or##视为某种贪婪/非贪婪修饰符。

如果您必须对路径部分进行一些更复杂的提取,这可能会很有用。

  • 当使用 `${...##...}` 和朋友而不是 `dirname` 和 `basename` 时要小心,它们在所有情况下都不起作用。例如,如果`$0` 不包含`/`,`${0##*/}` 和`${0%/*}` 都会扩展为与`$0` 相同的内容。 (5认同)