我如何在bash脚本中仅获得当前的工作目录名称,甚至更好,仅通过终端命令。
pwd
提供当前工作目录的完整路径,例如,/opt/local/bin
但我只想要bin
我如何在bash脚本中仅获得当前的工作目录名称,甚至更好,仅通过终端命令。
pwd
提供当前工作目录的完整路径,例如,/opt/local/bin
但我只想要bin
Answers:
不需要基名,特别是不需要运行pwd的子shell(它增加了额外且昂贵的fork操作);Shell可以使用参数扩展在内部执行此操作:
result=${PWD##*/} # to assign to a variable
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
printf '%s\n' "$result"
或者,不带extglob
:
dirname="/path/to/somewhere//"
result="${dirname%"${dirname##*[!/]}"}" # extglob-free multi-trailing-/ trim
result="${result##*/}" # remove everything before the last /
$PWD
是内置bash变量的名称;所有内置变量名都用大写字母(以将其与局部变量区分开,局部变量应始终至少具有一个小写字符)。result=${PWD#*/}
确实不评估为/full/path/to/directory
; 相反,它仅剥离第一个元素,使其成为path/to/directory
;使用两个#
字符会使模式与贪婪匹配,并尽可能匹配多个字符。阅读答案中链接的参数扩展页面以获取更多信息。
pwd
并不总是与的值相同。这过去在处理自动挂载的目录时特别令人讨厌,在这种情况下,记录物理路径而不是逻辑路径会生成一条路径,如果使用该路径,则该路径将允许自动挂载器自发卸除正在使用的目录。$PWD
cd
-o physical
sh
和csh
,如果你想退格键工作,你必须阅读整个stty
手册页,我们喜欢它!”
使用该basename
程序。对于您的情况:
% basename "$PWD"
bin
basename
程序的目的吗?除了缺少引号外,这个答案还有什么问题?
basename
的确是一个外部程序,做正确的事情,但运行任何外部程序的一件事Bash可以只使用内置的功能是愚蠢的做外的开箱,招致性能的影响(fork()
,execve()
,wait()
等)为没有理由。
basename
在这里不适用dirname
,因为dirname
具有的功能,${PWD##*/}
不-转化没有斜线为字符串.
,例如。因此,尽管dirname
用作外部工具会增加性能开销,但它也具有有助于补偿这些功能的功能。
function
关键字与POSIX不兼容,没有在标准语法上添加任何值,并且缺少引号会在带有空格的目录名称中产生错误。wdexec() { "./$(basename "$PWD")"; }
可能是一个更好的选择。
basename
“效率”较低。但是,它可能更多的在开发人员的生产力方面的效率,因为它很容易比较丑陋的bash命令,应该牢记。因此,如果您还记得它,那就去吧。否则,basename
效果也一样。有没有人不得不提高bash脚本的“性能”并使之更有效?
您可以结合使用pwd和basename。例如
#!/bin/bash
CURRENT=`pwd`
BASENAME=`basename "$CURRENT"`
echo "$BASENAME"
exit;
grep怎么样:
pwd | grep -o '[^/]*$'
pwd | xargs basename
,但并不是那么重要。但是其他答案在整个环境中都更简单,更一致
我喜欢选定的答案(Charles Duffy),但是如果您在符号链接目录中,并且想要目标目录的名称,请小心。不幸的是,我认为不能在单个参数扩展表达式中完成此操作,也许我误会了。这应该工作:
target_PWD=$(readlink -f .)
echo ${target_PWD##*/}
要看到这一点,可以进行一个实验:
cd foo
ln -s . bar
echo ${PWD##*/}
报告“栏”
要显示路径的前导目录(不产生/ usr / bin / dirname的fork-exec):
echo ${target_PWD%/*}
这将例如转换foo / bar / baz-> foo / bar
readlink -f
它是GNU扩展,因此在BSD(包括OS X)上不可用。
echo "$PWD" | sed 's!.*/!!'
如果您使用的是Bourne shell或${PWD##*/}
不可用。
${PWD##*/}
是POSIX sh-每个现代的/ bin / sh(包括破折号,灰烬等)都支持它;要在最近的机器上运行实际的Bourne,您需要安装在较旧的Solaris系统上。除此之外- echo "$PWD"
; 省略引号会导致错误(如果目录名称包含空格,通配符等)。
令人惊讶的是,没有人提到仅使用内置bash命令的替代方法:
i="$IFS";IFS='/';set -f;p=($PWD);set +f;IFS="$i";echo "${p[-1]}"
作为一个额外的奖励,你可以很容易地获得与父目录的名称:
[ "${#p[@]}" -gt 1 ] && echo "${p[-2]}"
这些将在Bash 4.3-alpha或更高版本上运行。
basename $(pwd)
要么
echo "$(basename $(pwd))"
pwd
传递给之前先对其进行字符串分割和glob扩展basename
。
basename "$(pwd)"
-虽然相比,只是这是非常低效的basename "$PWD"
,这是本身效率不高相比,使用参数扩展而不是调用basename
的。
只需使用:
pwd | xargs basename
要么
basename "`pwd`"
xargs
当目录名包含文字换行符或引号字符,并且第二个公式调用pwd
命令时,formultion效率低下且有错误而不是通过内置的变量扩展检索相同的结果。
如果只想在bash提示区域中看到当前目录,则可以在中编辑.bashrc
文件~
。更改\w
到\W
该行:
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
跑 source ~/.bashrc
,它将仅在提示区域中显示目录名称。
参考:https : //superuser.com/questions/60555/show-only-current-directory-name-not-full-path-on-bash-prompt
我非常喜欢使用gbasename
GNU coreutils的一部分。
basename
在那儿被调用。通常仅gbasename
在MacOS和其他非GNU基本名称附带的平台上调用它。
以下命令将以bash脚本打印当前工作目录。
pushd .
CURRENT_DIR="`cd $1; pwd`"
popd
echo $CURRENT_DIR
$1
要包含当前工作目录的参数列表。(2)pushd
和popd
在这里毫无用处,因为反引号内部的所有操作都在子shell中完成-因此它不会影响父shell的目录。(3)使用"$(cd "$1"; pwd)"
带有空格的目录名称将更具可读性和弹性。