如何从文件路径中提取目录路径?

Posted

技术标签:

【中文标题】如何从文件路径中提取目录路径?【英文标题】:How to extract directory path from file path? 【发布时间】:2011-09-01 12:59:32 【问题描述】:

在 Bash 中,如果是 VAR="/home/me/mydir/file.c",我如何获得 "/home/me/mydir"

【问题讨论】:

这里有更精巧复杂的真实目录路径解析***.com/questions/29789204/… 【参考方案1】:

dirnamebasename 是您正在寻找的用于提取路径组件的工具:

$ VAR='/home/pax/file.c'
$ DIR="$(dirname "$VAR")" ; FILE="$(basename "$VAR")"
$ echo "[$DIR] [$FILE]"
[/home/pax] [file.c]

它们不是内部的 bash 命令,但它们是 POSIX 标准的一部分 - 请参阅 dirnamebasename。因此,它们可能在大多数能够运行bash 的平台上可用或可以获得。

【讨论】:

为什么在变量名周围使用括号,而不是“$VAR”? ***.com/questions/8748831/… 回答了上述问题。 @user658182 在这个特定的例子中,这是出于习惯,而不是必要。 export 是不必要的,echos are useless. @tripleee:export 是我的习惯,只是为了确保将变量传递给子shell。 echo 语句用于展示如何将输出转换为变量,但我可能应该全力以赴(我现在拥有)。尽管这些都不会真正影响答案的“肉”,但我会进行调整。对于改进我的答案的建设性批评,我总是很感激。【参考方案2】:
$ export VAR=/home/me/mydir/file.c
$ export DIR=$VAR%/*
$ echo "$DIR"
/home/me/mydir

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

为了避免依赖basenamedirname

【讨论】:

因为两者都是 POSIX 的一部分,所以依赖应该不是问题。 orkoden ,你是对的。我回答的目的是表明没有义务执行两个额外的过程。 bash 对于用例来说是自给自足的。 我正在使用 Emmanuel 的方法,因为我希望传递文件或文件夹名称,然后计算文件夹路径。使用这个正则表达式是正确的,而 dirname 函数在我输入文件夹时返回父文件夹。 但是,如果 $VAR 中没有路径信息,$VAR%/*/test 会产生一个意外的值,等于 $VAR/test 而 $(dirname $VAR) 会产生更可预测的值和适当的 ./test 值。这很重要,因为前者会尝试将文件名视为目录,而后者则可以。 这应该是公认的答案。 dirnamebasename 有它们的位置,但如果路径已经在 shell 变量中,使用 shell 的内置工具比调用外部进程更高效和优雅。【参考方案3】:

在相关说明中,如果您只有文件名或相对路径,dirname 本身将无济于事。对我来说,答案最终是readlink

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

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

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

【讨论】:

如果不存在多个路径组件,您应该使用readlink -m "$fname" 递归地规范化给定名称【参考方案4】:

如果您关心目标文件是符号链接,首先您可以检查它并获取原始文件。下面的 if 子句可能会对您有所帮助。

if [ -h $file ]
then
 base=$(dirname $(readlink $file))
else
 base=$(dirname $file)
fi

【讨论】:

【参考方案5】:
HERE=$(cd $(dirname $BASH_SOURCE) && pwd)

new_path=$(dirname $BASH_SOURCE[0]) 获取完整路径的位置。您使用cd new_path 更改当前目录,然后运行pwd 以获取当前目录的完整路径。

【讨论】:

太棒了,最多态的选项! 这实际上似乎是对另一个问题的回答。 The quoting is broken.【参考方案6】:

我正在玩这个并想出了一个替代方案。

$ VAR=/home/me/mydir/file.c

$ DIR=`echo $VAR |xargs dirname`

$ echo $DIR
/home/me/mydir

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

$ DIR=`echo $VAR |xargs dirname |xargs dirname |xargs dirname`

$ echo $DIR
/home

【讨论】:

【参考方案7】:

您可以使用How to find the last field using 'cut' 的方法尝试这样的事情:

说明

rev/home/user/mydir/file_name.c 反转为 c.eman_elif/ridym/resu/emoh/ cut 使用/ 作为分隔符,并选择第二个字段,即ridym/resu/emoh/,删除字符串直到/ 第一次出现 最后,我们再次反转得到/home/user/mydir
$ VAR="/home/user/mydir/file_name.c"
$ echo $VAR | rev | cut -d"/" -f2- | rev
/home/user/mydir

【讨论】:

不建议将“/”(在文件名中无效)替换为空格(在文件名中有效)。如果您必须使用这样的解决方案,最好只删除所有内容,直到最后一个“/”字符,包括最后一个“/”字符。 @MartynDavis 请根据您的建议查看我的更新答案 这不是 OP 要求的。 @m42 根据 OP 要求更新了我的答案。请查看其更新版本。 @alper;是的,现在这就是 OP 所要求的。 :)【参考方案8】:

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

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

【讨论】:

find 的输出上使用for 循环是一种反模式,也是许多错误的根源。这种构造本质上是有限的,如果find 产生的结果包含空格或其他shell 元字符,更不用说换行符了。

以上是关于如何从文件路径中提取目录路径?的主要内容,如果未能解决你的问题,请参考以下文章

提取目录路径和文件名

如何从 Python 中的文件路径中提取文件夹路径?

从路径中提取目录[重复]

如何从日志文件路径中提取变量,测试 Logstash 中模式的日志文件名?

python 从路径目录,文件基名和文件扩展名中分离/提取

从 OpenFileDialog 路径/文件名中提取路径