Bash Shell实现basename

Bash Shell实现basename,basename 命令可以做到你想要的,但是能够在不调用外部命令的情况下得到相同的结果吗?bash 的字符串操作能不能做到?

解决方案

是的,bash 能够从 shell 变量中剥离路径中的目录,只留下最后一部分(文件名)。当你想按以下方式写时:

FILE=$(basename $FULLPATHTOFILE)

其实只需要写成:

FILE=${FULLPATHTOFILE##*/}

讨论

这两种写法的不同之处在于花括号。第一种写法使用的是括号,它会生成一个子 shell 来执行参数值为 $FULLPATHTOFILE 的命令 basename。第二种写法使用的花括号只是 shell 变量替换语法的一部分,并不会生成子 shell,也不会执行命令。它从字符串起始位置开始(因为 #)查找并删除匹配模式 */ 的最长子串(因为 ##)。* 匹配任意数量的字符,/仅代表其字面含义。对于路径 /usr/local/bin/mycmd,指定模式会匹配(并删除)/usr/local/bin/,将剩下的 mycmd 赋给变量 $FILE

因为 basename 命令会忽略路径结尾的 /,所以 $(basename /usr/local/bin/)会返回 bin,而我们用 bash 所实现的版本则返回空串(因为模式 */ 所能匹配的最长内容就是整个字符串)。为了与 basename 兼容,第一件事就是删除路径结尾的 /

真正的 basename 命令还可以将要删除的后缀作为第二个可接受的参数。bash 也可以做到,只是需要额外多加一步。所以,对于:

FILE=$(basename $MYIMAGEFILE .jpg)

更完整的替代方案是:

FILE=${MYIMAGEFILE%/}  # 删除结尾的/
FILE=${FILE##*/}       # 删除结尾/之前的所有字符
FILE=${FILE%.jpg}      # 如果存在,删除后缀.jpg

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!