Bash one-liner用于隔离目录名

时间:2017-01-19 23:25:00

标签: bash string-substitution

在Bash,v.4.3.11(1)中我有这个示例代码:

#!/bin/bash

dir=("/home/user/Documents/" "/home/user/Music/" "/home/user/Videos/" \
"/home/user/Photos/")

baseDir="/home/user/"

for i in "${!dir[@]}"
do
    niceName=${dir[$i]#"$baseDir"}  # removes baseDir from front part
    printf "%s\n" "${niceName%"/"}"  # also removes trailing slash from end
done

有没有办法将两个命令合二为一,并且在for循环中只有printf? (最好不要求助于awk或sed,但如果不可避免的话,那就好吧。)

我尝试了各种组合,但最终出现了“错误的替代”错误。 例如,printf "%s\n" "${niceName=${dir[$i]#"$baseDir"%"/"}"对我不起作用。

4 个答案:

答案 0 :(得分:3)

这是一个更简单的版本。

#!/bin/bash
dir=("/home/user/Documents/" "/home/user/Music/" "/home/user/Videos/" "/home/user/Photos/")

for d in "${dir[@]}"
do
  basename "$d"
done

请注意,需要引用basename的参数,否则带有某些字符(如空格)的目录名将导致问题。

循环内部也可以被下面的基于内置的解决方案所取代(更快,没有外部依赖):

  d="${d%/}"
  echo "${d##*/}"

答案 1 :(得分:2)

如果你正在寻找使用替代的单行班,那么这将会有效:

dir=("/home/user/Documents/" "/home/user/Music/" "/home/user/Videos/" \
"/home/user/Photos/")
baseDir="/home/user/"
dir=("${dir[@]%/}")    ## This line removes trailing forward slashes
printf "%s\n" "${dir[@]#$baseDir}"

答案 2 :(得分:1)

您可以使用仅返回基本文件名的basename。在这种情况下,您的文件是目录。

#!/bin/bash
dir=("/home/user/Documents/" "/home/user/Music/" "/home/user/Videos/" "/home/user/Photos/")

for i in "${!dir[@]}"
do
  echo $( basename ${dir[$i]})
done

答案 3 :(得分:1)

据我所知bash不处理“双参数扩展”(我相信zsh确实如此)。但是,您可以将这样的解决方案合并在一起:

dir=("/home/user/Documents/" "/home/user/Music/" "/home/user/Videos/" "/home/user/Photos/")
trunk=/home/user/

echo $(dir=( "${dir[@]##${trunk}}" ); echo "${dir[@]%/}")