如何获取复杂文件的基名

mai*_*ash 3 shell

这是文件路径的示例:

/isf/GCM/VPfig/Aas/AR/ClCo el Doma Republic/VMN CRTro.txt
Run Code Online (Sandbox Code Playgroud)

我想得到的是文件基名:

VMN CRTro.txt
Run Code Online (Sandbox Code Playgroud)

所以我尝试以下操作:

echo /isf/GCM/VPfig/Aas/AR/ClCo el Doma Republic/VMN CRTro.txt | sed s'/\// /g' | awk '{print $NF}'
CRTro.txt     <-- not as expected
Run Code Online (Sandbox Code Playgroud)

或者

basename  /isf/GCM/VPfig/Aas/AR/ClCo el Doma Republic/VMN CRTro.txt
basename: extra operand `Doma'
Try `basename --help' for more information.     <-- basename cant handle spaces 
Run Code Online (Sandbox Code Playgroud)

获取包含空格的文件的基本名称的最佳方法是什么?

小智 18

只引用你的路径

basename  "/isf/GCM/VPfig/Aas/AR/ClCo el Doma Republic/VMN CRTro.txt"
Run Code Online (Sandbox Code Playgroud)

  • 当然单引号在这里比双引号更安全。否则,如果文件名包含 shell 可以扩展的任何内容,shell 将执行该扩展,这不会是所需的结果。 (2认同)

phe*_*mer 11

问题的核心是引用。没有引号,它将文件名视为basename.
如果路径是硬设置的,而不是变量,那么 rob 的答案是好的。但是,如果这是使用变量的脚本的一部分,则有两个很好的解决方案:

$ filepath="/isf/GCM/VPfig/Aas/AR/ClCo el Doma Republic/VMN CRTro.txt"
$ basename "$filepath"
VMN CRTro.txt
Run Code Online (Sandbox Code Playgroud)

然而,它basename是一个外部实用程序,而不是 bash 的一部分。bash 中内置了一个替代解决方案:

$ filepath="/isf/GCM/VPfig/Aas/AR/ClCo el Doma Republic/VMN CRTro.txt"
$ echo "${filepath##*/}"
VMN CRTro.txt
Run Code Online (Sandbox Code Playgroud)

${filepath##*/}是告诉bash执行水珠*/,这尽可能多的字符可能后跟一个相匹配/,然后剥离出来。

  • 关于`basename` 与`${var##*/}` 的常见警告:它不能正常用于`path/to/dir/` 或`/`。您需要 `basename -- "$filepath"`(对于以 `-` 开头的路径)。 (6认同)