关于bash:从文件路径获取文件目录路径

Get file directory path from file path

在巴什,如果VAR="/home/me/mydir/file.c",我怎么得到"/home/me/mydir"


dirnamebasename是您要提取路径组件的工具:

1
2
3
4
5
6
7
8
9
$ VAR=/home/me/mydir/file.c

$ DIR=$(dirname"${VAR}")

$ echo"${DIR}"
/home/me/mydir

$ basename"${VAR}"
file.c

它们不是内部bash命令,但它们是posix标准的一部分(参见dirnamebasename),因此大多数运行bash的系统都可以使用它们。


1
2
3
4
5
6
7
$ export VAR=/home/me/mydir/file.c
$ export DIR=${VAR%/*}
$ echo"${DIR}"
/home/me/mydir

$ echo"${VAR##*/}"
file.c

避免依赖basenamedirname


在相关的注释中,如果您只有文件名或相对路径,那么单独使用dirname不会有帮助。对我来说,答案最终是readlink

1
2
3
fname='txtfile'    
echo $(dirname"$fname")                # output: .
echo $(readlink -f"$fname")            # output: /home/me/work/txtfile

然后,您可以将这两者结合起来,得到目录。

1
echo $(dirname $(readlink -f"$fname")) # output: /home/me/work


如果您希望目标文件是符号链接,首先可以检查它并获取原始文件。下面的if子句可以帮助您。

1
2
3
4
5
6
if [ -h $file ]
then
 base=$(dirname $(readlink $file))
else
 base=$(dirname $file)
fi

我在玩这个,想出了另一个办法。

1
2
3
4
5
6
$ VAR=/home/me/mydir/file.c

$ DIR=`echo $VAR |xargs dirname`

$ echo $DIR
/home/me/mydir

我喜欢的部分是很容易扩展备份树:

1
2
3
4
$ DIR=`echo $VAR |xargs dirname |xargs dirname |xargs dirname`

$ echo $DIR
/home

这是我用于递归剪裁的脚本。当然,用您想要的目录替换$1。

1
2
3
4
5
6
7
8
9
10
11
BASEDIR="$1"
IFS=$'
'

cd $BASEDIR
 for f in $(find . -type f -name ' *')
 do
    DIR=$(dirname"$f")
    DIR=${DIR:1}
    cd $BASEDIR$DIR
    rename 's/^ *//' *
 done


首先,我用空位(代替了/)。然后,我删除了任何空格前的所有字符()。最后,我删除了第一个字符,即空白()。

1
2
3
4
$ VAR="/home/me/mydir/file.c"

$ echo $VAR | tr '/' ' ' | sed 's/^.* / /' | cut -c2-
file.c