在Bash中获取目录的父级

YTK*_*mba 183 directory bash dirname

如果我有一个文件路径,如...

/home/smith/Desktop/Test
/home/smith/Desktop/Test/
Run Code Online (Sandbox Code Playgroud)

如何更改字符串以使其成为父目录?

例如

/home/smith/Desktop
/home/smith/Desktop/
Run Code Online (Sandbox Code Playgroud)

Mic*_*man 285

dir=/home/smith/Desktop/Test
parentdir="$(dirname "$dir")"
Run Code Online (Sandbox Code Playgroud)

如果有斜杠也可以工作.

  • 里面的引号很重要,否则你将丢失所有数据 (12认同)
  • 我用来获取当前工作目录的父变种:`parentdir = $(dirname \`pwd \`)` (8认同)
  • @asdfasdfads 你能解释一下你的评论吗?如果省略引号,为什么数据会丢失? (3认同)
  • @Christopher Shroba是的,我省略了引号然后我的硬盘最终部分擦除了.我不记得究竟发生了什么:大概是一个未加引号的空白目录使它删除了父目录而不是目标 - 我的脚本刚删除了/ home/xxx /文件夹. (3认同)
  • 哦,好吧,除非你已经发出删除命令,否则没有任何关于导致任何数据丢失的命令,对吧?这只是一个问题,你试图删除在空间角色上拆分并删除远远超出预期的路径? (3认同)
  • 请注意,此方法对于“丑陋”的名称是不安全的。诸如“ -rm -rf”之类的名称将破坏所需的行为。可能是“。” 也会。我不知道这是否是最好的方法,但是我在这里创建了一个单独的“以正确性为中心”的问题:http://stackoverflow.com/questions/40700119/get-parent-directory-for-a-file-流行 (2认同)

And*_*ler 17

......但是"在这里看到的"被打破了.这是修复:

> pwd
/home/me
> x='Om Namah Shivaya'
> mkdir "$x" && cd "$x"
/home/me/Om Namah Shivaya
> parentdir="$(dirname "$(pwd)")"
> echo $parentdir
/home/me
Run Code Online (Sandbox Code Playgroud)


aih*_*iho 12

如果您只需要父目录的名称:

parent_dir_name=$(basename $(dirname $PWD))
Run Code Online (Sandbox Code Playgroud)


Ria*_*zvi 11

显然,通过简单地附加点 - 点文件名来给出父目录:

/home/smith/Desktop/Test/..     # unresolved path
Run Code Online (Sandbox Code Playgroud)

但您必须要求已解析的路径(没有任何点 - 点路径组件的绝对路径):

/home/smith/Desktop             # resolved path
Run Code Online (Sandbox Code Playgroud)

使用的最佳答案的问题dirname是,当您输入带点点的路径时它们不起作用:

$ dir=~/Library/../Desktop/../..
$ parentdir="$(dirname "$dir")"
$ echo $parentdir
/Users/username/Library/../Desktop/..   # not fully resolved
Run Code Online (Sandbox Code Playgroud)

这更强大:

dir=/home/smith/Desktop/Test
parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`
Run Code Online (Sandbox Code Playgroud)

您可以提供它/home/smith/Desktop/Test/..,但也可以提供更复杂的路径,例如:

$ dir=~/Library/../Desktop/../..
$ parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`
$ echo $parentdir
/Users                                  # the fully resolved path!
Run Code Online (Sandbox Code Playgroud)

  • 你根本不需要`eval`:只需执行`parentdir=$(cd -- "$dir" && pwd)`。由于“cd”在子 shell 中运行,因此您不需要“cd”回到我们原来的位置。此处的“--”是为了防止“$dir”的扩展以连字符开头。“&&”只是为了防止“cd”失败时“parentdir”有非空内容。 (3认同)

Sté*_*hon 11

另一个答案的动机

我喜欢非常简短、清晰、有保证的代码。如果它不运行外部程序,那么加分点是,因为您需要处理大量条目的那一天,它会明显更快。

原则

不确定您拥有和想要的保证,因此无论如何都要提供。

如果你有保证,你可以用很短的代码来做到这一点。这个想法是使用 bash 文本替换功能来剪切最后一个斜杠和后面的任何内容。

从原始问题的简单到更复杂的情况下回答。

如果路径保证结束没有任何斜线(进出)

P=/home/smith/Desktop/Test ; echo "${P%/*}"
/home/smith/Desktop
Run Code Online (Sandbox Code Playgroud)

如果保证路径以恰好一个斜杠(输入和输出)结尾

P=/home/smith/Desktop/Test/ ; echo "${P%/*/}/"
/home/smith/Desktop/
Run Code Online (Sandbox Code Playgroud)

如果输入路径可能以零或一个斜杠(不是更多)结尾,并且您希望输出路径以没有斜杠结尾

for P in \
    /home/smith/Desktop/Test \
    /home/smith/Desktop/Test/
do
    P_ENDNOSLASH="${P%/}" ; echo "${P_ENDNOSLASH%/*}"
done

/home/smith/Desktop
/home/smith/Desktop
Run Code Online (Sandbox Code Playgroud)

如果输入路径可能有很多多余的斜线,并且您希望输出路径没有斜线结束

for P in \
    /home/smith/Desktop/Test \
    /home/smith/Desktop/Test/ \
    /home/smith///Desktop////Test// 
do
    P_NODUPSLASH="${P//\/*(\/)/\/}"
    P_ENDNOSLASH="${P_NODUPSLASH%%/}"
    echo "${P_ENDNOSLASH%/*}";   
done

/home/smith/Desktop
/home/smith/Desktop
/home/smith/Desktop
Run Code Online (Sandbox Code Playgroud)


小智 10

只需echo $(cd ../ && pwd)在您要查找其父目录的目录中工作时使用.该链还具有不具有斜杠的附加益处.


Jon*_*and 7

如果/home/smith/Desktop/Test/../你想要的话:

dirname 'path/to/child/dir'
Run Code Online (Sandbox Code Playgroud)

如看到这里.