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


0

Shell变量包含路径。一个人如何获得其文件名部分?

在bash(1)中,我进行了实验,发现可以使用."${i/*\///}"where i是环境变量的名称来进行操作。这种方法不仅丑陋,而且在路径不包含任何/字符的情况下也是错误的。

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

$ for i in /source/path/*.pdf; do\
  ln -s "$i" ."${i/*\///}"; \
  done

2
例如,如果您不需要点,只需ln -s "$i"将目标的基本名称自动用作链接名称。也是nit:这是一个shell变量(或shell参数),但不是环境变量,因为您没有export。在外壳程序中它们都可以工作,但是如果您想将信息传递给另一个程序,则区别很重要。
dave_thompson_085 '18

Answers:


5

${i##*/}

这部作品在Posix的炮弹,其中包括bashdashkshzsh,等从标准POSIX参数扩展部分 POSIX的壳牌及公用事业规格:

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

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

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

mybasename() { echo "${1##*/}"; }

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


1
另请参见man basename标准POSIX参数扩展
库萨兰达

3
我发现我basename的下一个代码维护者比参数扩展更容易阅读
Tankman六四

0

您可以将路径放入变量中,并使用其长度计数从完整路径名中仅获取所需的子字符串,如下所示:

$ pth="/source/path/";
$ for i in $path*.pdf; do \
  ln -s "$i" ./"${i:${#pth}}"; \
  done
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.