如何从文件路径中提取目录路径?
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】:dirname
和 basename
是您正在寻找的用于提取路径组件的工具:
$ VAR='/home/pax/file.c'
$ DIR="$(dirname "$VAR")" ; FILE="$(basename "$VAR")"
$ echo "[$DIR] [$FILE]"
[/home/pax] [file.c]
它们不是内部的 bash
命令,但它们是 POSIX 标准的一部分 - 请参阅 dirname
和 basename
。因此,它们可能在大多数能够运行bash
的平台上可用或可以获得。
【讨论】:
为什么在变量名周围使用括号,而不是“$VAR”? ***.com/questions/8748831/… 回答了上述问题。 @user658182 在这个特定的例子中,这是出于习惯,而不是必要。export
是不必要的,echo
s 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
为了避免依赖basename
和dirname
【讨论】:
因为两者都是 POSIX 的一部分,所以依赖应该不是问题。 orkoden ,你是对的。我回答的目的是表明没有义务执行两个额外的过程。 bash 对于用例来说是自给自足的。 我正在使用 Emmanuel 的方法,因为我希望传递文件或文件夹名称,然后计算文件夹路径。使用这个正则表达式是正确的,而 dirname 函数在我输入文件夹时返回父文件夹。 但是,如果 $VAR 中没有路径信息,$VAR%/*/test 会产生一个意外的值,等于 $VAR/test 而 $(dirname $VAR) 会产生更可预测的值和适当的 ./test 值。这很重要,因为前者会尝试将文件名视为目录,而后者则可以。 这应该是公认的答案。dirname
和 basename
有它们的位置,但如果路径已经在 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 元字符,更不用说换行符了。以上是关于如何从文件路径中提取目录路径?的主要内容,如果未能解决你的问题,请参考以下文章