如何从shell变量获取路径的文件名部分

Tan*_*n六四 0 environment-variables filenames basename variable

shell 变量保存一个路径。如何获得它的文件名部分?

在bash(1)中,我试验了一下,发现用."${i/*\///}"where iis环境变量名就可以了。这种方法不仅难看,而且在路径不包含任何/字符的情况下也是错误的。

我将演示一个需要此类功能的实际案例。假设我们要为源目录中的每个 PDF 文件建立一个指向当前目录的符号链接。

$ for i in /source/path/*.pdf; do\
  ln -s "$i" ."${i/*\///}"; \
  done
Run Code Online (Sandbox Code Playgroud)

Rob*_*rtL 5

${i##*/}

这适用于 Posix shell,包括bashdashkshzsh等。 来自Posix Shell & Utilities 规范的标准POSIX 参数扩展部分

${parameter##[word]}
删除最大的前缀模式。这个词应该被扩展以产生一个模式。然后参数扩展将导致参数,其中与删除模式匹配的前缀的最大部分。

或者,传统上,该basename命令已用于此目的。 注意:性能可能会成为一个重要问题,因为它basename是作为外部命令实现的(例如,/usr/bin/basename)。因为您是在循环内执行此操作,所以您将为每个文件调用一个外部命令。在 1000 个文件的列表中,这可能是 0.05 秒(参数扩展)和 2.0 秒(basename命令)之间的差异。但是对于 10,000 个文件的列表,可能是 0.5 秒(扩展)与 20 秒 ( basename)之间的差异。随着文件数量的增加,性能差异变得更加极端。

为了可读性和性能,您可以实现自己的basename功能,例如:

mybasename() { echo "${1##*/}"; }
Run Code Online (Sandbox Code Playgroud)

(为函数选择更好的名称,和/或完整basename命令行界面的实现,留给读者作为练习。:)

  • 我发现对于我的代码的下一个维护者来说,`basename` 比参数扩展更容易阅读 (3认同)