在 bash 中获取目录或文件的基本名称的快速且正确的方法

问题描述 投票:0回答:3

我有这个代码:

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

这一切正常,直到我们有 1 个或多个 尾部斜杠

我已经找到了如何修复它的解决方案,但是 问题是我们需要启用

extglob
,但我不需要 想要那个:

ari@ari-gentoo ~ % x='/home/ari///'

ari@ari-gentoo ~ % echo "${x%%+(/)}"
/home/ari

然后我们可以将其保存到 tmp var 中并运行基本名称 替换它

无论如何,我的问题是,有没有合适的方法可以做到这一点 而且它仍然很快(意味着没有调用外部命令 因为这个函数被调用了很多)而不 需要启用任何奇特的功能吗?

谢谢您的提前答复:)

问题与解答

否,因为所有这些解决方案要么使用命令,要么具有仅删除最后一个斜杠而不是多个斜杠的替换表达式:)(例如 /home/ari/// 带有 expr ${x%/} 将仅变为 /home/ari // 当它需要是 /home/ari 时)

    “适当”是什么意思
我所说的“正确”是指“在不启用 extglob 或任何其他奇特功能的情况下实现的”

linux bash shell substitution basename
3个回答
3
投票
这是一种方法:

get_base() { set -- "${1%"${1##*[!/]}"}" printf '%s\n' "${1##*/}" }
$ get_base /home/oguz//
oguz
$ get_base /root
root
$ get_base /

$ get_base .bash_history
.bash_history
    

2
投票
在 bash 中快速正确地获取...

作为对

oguz ismail 的正确答案的补充,我建议使用 -v

 标志来实现这种功能,以减少分叉:

get_base() { if [[ $1 == -v ]] ;then local -n _res=$2 shift 2 else local _res fi set -- "${1%"${1##*[!/]}"}" printf -v _res %s "${1##*/}" [[ ${_res@A} == _res=* ]] && echo "$_res" }
这可以让你尝试这个功能

$ get_base /path/entry//// entry
但是为了将结果存储到某个变量中,你会

避免无用的分叉,就像

myvar=$(get_base /path/entry////)

并使用首选语法:

$ get_base -v myvar /path/entry//// $ echo $myvar entry
成为 

split entry
path
 的函数:

get_base() { if [[ $1 == -v ]] ;then local -n _res=$2 shift 2 else local _res fi set -- "${1%"${1##*[!/]}"}" printf -v _res %s "${1##*/}" [[ ${_res@A} == _res=* ]] && echo "$_res" "${1%/$_res}" && return printf -v _res[1] %s "${1%/$_res}" }
然后:

$ get_base /path/to/entry//// entry /path/to

$ get_base -v myvar /path/to/entry//// $ declare -p myvar declare -a myvar=([0]="entry" [1]="/path/to") $ echo ${myvar[0]} entry $ echo ${myvar[1]} /path/to
带有空格的 unicode 文件名:

$ get_base -v myvar '/path/to/some dir/some loved file ♥♥♥.xtns' $ declare -p myvar declare -a myvar=([0]="some loved file ♥♥♥.xtns" [1]="/path/to/some dir")
    

2
投票
想法:

get_base() { [[ $1 =~ ([^/]*)/*$ ]]; echo "${BASH_REMATCH[1]}"; }; get_base() { while [[ "${1%/}" != "$1" ]]; do set -- "${1%%/}"; done; echo "${1##*/}"; }
    
© www.soinside.com 2019 - 2024. All rights reserved.