如何在bash脚本或终端命令中获取当前工作目录/文件夹的名称?
pwd
可以给出当前工作目录的完整路径,例如/opt/local/bin
,但我只需要bin
。
不需要使用basename,尤其不需要运行pwd的子shell(这会增加一次昂贵的fork操作);shell可以内部使用参数展开来完成此操作:
result=${PWD##*/} # to assign to a variable
result=${result:-/} # to correct for the case where PWD=/
printf '%s\n' "${PWD##*/}" # to print to stdout
# ...more robust than echo for unusual names
# (consider a directory named -e or -n)
printf '%q\n' "${PWD##*/}" # to print to stdout, quoted for use as shell input
# ...useful to make hidden characters readable.
请注意,如果您在其他情况下(不是使用PWD
,而是其他变量保存目录名称),则可能需要修剪任何尾随斜杠。以下内容使用bash的extglob支持,即使有多个尾随斜杠也可以正常工作: dirname=/path/to/somewhere//
shopt -s extglob # enable +(...) glob syntax
result=${dirname%%+(/)} # trim however many trailing slashes exist
result=${result##*/} # remove everything before the last / that still remains
result=${result:-/} # correct for dirname=/ case
printf '%s\n' "$result"
如果不使用 extglob
,可以选择以下方法:
dirname="/path/to/somewhere//"
result="${dirname%"${dirname##*[!/]}"}" # extglob-free multi-trailing-/ trim
result="${result##*/}" # remove everything before the last /
result=${result:-/} # correct for dirname=/ case
$PWD
是内置的bash变量名;所有内置变量名都是大写字母(以区分它们与本地变量,后者应始终至少有一个小写字符)。 result=${PWD#*/}
不会求值为/full/path/to/directory
;相反,它仅剥离第一个元素,使其成为path/to/directory
。使用两个#
字符使模式匹配贪婪匹配尽可能多的字符。阅读答案中链接的“参数展开页面”以获取更多信息。 - Charles Duffypwd
命令输出的结果和 $PWD
的值并不总是相同的,这是由于通过符号链接进行 cd
操作所引起的复杂情况,以及 bash 是否设置了 -o physical
选项等因素。在处理自动挂载目录时,情况尤为棘手,如果记录物理路径而非逻辑路径,则可能产生一个路径,如果使用该路径,会导致自动挂载程序自动卸载正在使用的目录。 - Alex North-Keyssh
和 csh
而且如果你想让退格键正常工作,你必须读整个 stty
的手册,而我们还是很喜欢它!”这样的话。 - Red Cricket使用basename
程序。对于你的情况:
% basename "$PWD"
bin
basename
程序的目的不就是这个吗?除了缺少引号之外,这个答案有什么问题吗? - Nachtbasename
实际上是一个能够完成正确任务的外部程序,但是对于任何bash可以通过内置功能轻松处理的任务来说,运行_任何_外部程序都是愚蠢的,这会带来性能影响(fork()
,execve()
,wait()
等),而且没有必要。 - Charles Duffybasename
的反对意见 不适用 于 dirname
,因为 dirname
拥有 ${PWD##*/}
没有的功能——例如将不含斜杠的字符串转换为 .
。因此,虽然使用 dirname
作为外部工具会带来性能开销,但它也拥有有助于弥补同样缺陷的功能。 - Charles Duffybasename
显然比使用繁琐的 bash 语法更易记,虽然在效率上不如后者,但从开发者的生产力角度来看,它可能更高效。因此,如果您记得它,就用它吧。否则,basename
也同样有效。是否有人曾经试图提高 bash 脚本的性能并使其更高效呢? - P.P$ echo "${PWD##*/}"
echo "${PWD##*/}"
。 - Charles Duffyname=${PWD##*/}
就是正确的,而name=$(echo "${PWD##*/}")
则是错误的(在不必要的效率方面)。 - Charles Duffy你可以结合使用pwd和basename。例如:
#!/bin/bash
CURRENT=`pwd`
BASENAME=`basename "$CURRENT"`
echo "$BASENAME"
exit;
使用:
basename "$PWD"
或者
IFS=/
var=($PWD)
echo ${var[-1]}
将内部文件名分隔符(IFS)改回空格。
IFS=
在 IFS 后面有一个空格。
grep怎么样:
pwd | grep -o '[^/]*$'
pwd | xargs basename
没有... 可能并不那么重要,但另一个答案更简单,并且在各种环境下更加一致。 - davidhqbasename $(pwd)
或者echo "$(basename $(pwd))"
pwd
命令的输出在传递给basename
之前进行了字符串分割和通配符扩展。 - Charles Duffybasename "$(pwd)"
虽然与仅使用basename "$PWD"
相比非常低效,但与根本不调用basename
而使用参数扩展相比仍然低效。 - Charles Duffyecho "${PWD##*/}"
哈哈。 - undefined这个主题很棒!这里还有一种口味:
pwd | awk -F / '{print $NF}'
我喜欢所选答案(Charles Duffy),但如果您在符号链接的目录中并且想要目标目录的名称,请小心。不幸的是,我认为无法在单个参数扩展表达式中完成它,也许我错了。这应该可以解决问题:
target_PWD=$(readlink -f .)
echo ${target_PWD##*/}
为了看到这个,我们来做一个实验:
cd foo
ln -s . bar
echo ${PWD##*/}
报告 "bar"
显示路径的前导目录(不会产生 /usr/bin/dirname 的 fork-exec):
echo ${target_PWD%/*}
例如,这将把 foo/bar/baz 转换为 foo/bar。
echo "$PWD" | sed 's!.*/!!'
${PWD##*/}
不可用。${PWD##*/}
是 POSIX sh 的语法 -- 所有现代的/bin/sh (包括 dash、ash 等)都支持它;要在最近的系统上使用实际的 Bourne 语法,你需要在一个稍微旧一点的 Solaris 系统上。除此之外,用 echo "$PWD"
,省略引号可能会导致错误(如果目录名中有空格、通配符等)。 - Charles Duffy