在Bash中的文件路径参数中获取最后一个目录名/文件名


228

我正在尝试为SVN编写一个提交后钩子,该钩子驻留在我们的开发服务器上。我的目标是尝试自动将已提交项目的副本检出到服务器上托管的目录。但是,我需要能够仅读取传递给脚本的目录字符串中的最后一个目录,以便签出到托管我们项目的同一子目录。

例如,如果我对项目“ example”进行SVN提交,则我的脚本将“ / usr / local / svn / repos / example”作为其第一个参数。我只需要从字符串末尾得到“ example”,然后将其与另一个字符串连接起来,这样我就可以签出到“ / server / root / example”并立即看到更改。

Answers:


344

basename 确实删除路径的目录前缀:

$ basename /usr/local/svn/repos/example
example
$ echo "/server/root/$(basename /usr/local/svn/repos/example)"
/server/root/example

2
基本名称绝对是我要寻找的。但是,如何获取存储在变量中的参数的基本名称呢?例如SUBDIR="/path/to/whatever/$(basename $1)"
TJ L

5
@ tj111:听起来就像是没有$1,或者$1是空的
做某事

不幸的是,如果您包装命令,那么basename不是一个好主意。只是要记住的一点
dtc

98

以下方法可用于获取路径名的任何路径:

some_path=a/b/c
echo $(basename $some_path)
echo $(basename $(dirname $some_path))
echo $(basename $(dirname $(dirname $some_path)))

输出:

c
b
a

1
不适用于具有空格的路径...您可以使用引号来克服...以某种方式起作用echo "$(basename "$(dirname "$pathname")")"
Ray Foss

75

Bash无需调用外部即可获得路径的最后一部分basename

subdir="/path/to/whatever/${1##*/}"

2
在我的Mac上,如果您要对数千个文件中的每个文件进行琐碎的操作,则使用子字符串表示法比dirname / basename的速度要快多个数量级。
乔治

1
d=/home/me/somefolder;subdir="/$d/${1##*/}"我结束了类似//home/me/somefolder//的$ d实际上来自循环for d in $(find $SOMEFOLDER -maxdepth 1 -type d);使用subdir=$(basename $d)的作品如预期。
Buttle Butkus,2015年

1
@ButtleButkus:您应该使用while而不是对(更好)for的输出进行迭代或使用globbing :(最后的斜杠的工作原理是-如果您可以在Bash 4中进行递归操作,但是会出现“参数列表过长”的消息可能)。请注意,命令的一部分代表脚本或函数的第一个参数。您可能需要使用或某些其他变量或参数规范,或者确保传入了参数findfind -print0 | xargs -0for d in $SOMEFOLDER/*/-type d**shopt -s globstar${1}${d##*/}$1
已暂停,直到另行通知。

2
@DennisWilliamson非常感谢您分享对于任何将来开始怀疑为什么它不起作用或我是这里唯一愚蠢的读者的😂。以上答案假定$1包含the path from which last component is to be taken out。我错过了那部分。我用例:target_path='/home/user/dir1/dir2/dir3/'; target_path="${target_path%/}"; last_component=${target_path##*/}; echo $last_component-作品😉
维奈Vissh

2
在这里看到的说明如何为什么 ${1##*/}的作品:unix.stackexchange.com/a/171786/15070
马修
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.