在 Bash 中获取目录的父目录

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8426058/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 21:18:35  来源:igfitidea点击:

Getting the parent of a directory in Bash

bashdirectorydirname

提问by YTKColumba

If I have a file path such as...

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

/home/smith/Desktop/Test
/home/smith/Desktop/Test/

How do I change the string so it will be the parent directory?

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

e.g.

例如

/home/smith/Desktop
/home/smith/Desktop/

回答by Michael Hoffman

dir=/home/smith/Desktop/Test
parentdir="$(dirname "$dir")"

Works if there is a trailing slash, too.

如果尾随斜线也有效。

回答by Andreas Spindler

...but what is "seen here" is broken. Here's the fix:

......但是“在这里看到”的东西被打破了。这是修复:

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

回答by Endu A-d

Just use echo $(cd ../ && pwd)while working in the directory whose parent dir you want to find out. This chain also has the added benefit of not having trailing slashes.

只需echo $(cd ../ && pwd)在要查找其父目录的目录中工作时使用。这个链还有一个额外的好处,就是没有尾部斜杠。

回答by Riaz Rizvi

Clearly the parent directory is given by simply appending the dot-dot filename:

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

/home/smith/Desktop/Test/..     # unresolved path

But you must want the resolvedpath (an absolute path without any dot-dot path components):

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

/home/smith/Desktop             # resolved path

The problem with the top answers that use dirname, is that they don't work when you enter a path with dot-dots:

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

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

This is more powerful:

这是更强大的

dir=/home/smith/Desktop/Test
parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`

You can feed it /home/smith/Desktop/Test/.., but also more complex paths like:

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

$ dir=~/Library/../Desktop/../..
$ parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`
$ echo $parentdir
/Users                                  # the fully resolved path!

EDIT: If it doesn't work, check that your cdhasn't been modified, as is sometimes common practice,

编辑:如果它不起作用,请检查您cd是否没有被修改,这是有时的常见做法,

$ which cd
cd is a function  #cd was modified to print extra info, so use "builtin cd" to override
cd ()
{
    builtin cd "$@";
    ls -FGAhp
}
...

回答by Jon Egeland

If /home/smith/Desktop/Test/../is what you want:

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

dirname 'path/to/child/dir'

as seen here.

这里所见。

回答by Stéphane Gourichon

Motivation for another answer

另一个答案的动机

I like very short, clear, guaranteed code. Bonus point if it does not run an external program, since the day you need to process a huge number of entries, it will be noticeably faster.

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

Principle

原则

Not sure about what guarantees you have and want, so offering anyway.

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

If you have guarantees you can do it with very short code. The idea is to use bash text substitution feature to cut the last slash and whatever follows.

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

Answer from simple to more complex cases of the original question.

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

If path is guaranteed to end without any slash (in and out)

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

P=/home/smith/Desktop/Test ; echo "${P%/*}"
/home/smith/Desktop

If path is guaranteed to end with exactly one slash (in and out)

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

P=/home/smith/Desktop/Test/ ; echo "${P%/*/}/"
/home/smith/Desktop/

If input path may end with zero or one slash (not more) and you want output path to end without slash

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

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

If input path may have many extraneous slashes and you want output path to end without slash

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

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

回答by Marcelo Lacerda

Depending on whether you need absolute paths you may want to take an extra step:

根据您是否需要绝对路径,您可能需要采取额外的步骤:

child='/home/smith/Desktop/Test/'
parent=$(dirname "$child")
abs_parent=$(realpath "$parent")

回答by Kaustubh

use this : export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")"if you want 4th parent directory

使用这个:export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")"如果你想要第四个父目录

export MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")"if you want 3rd parent directory

export MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")"如果你想要第三个父目录

export MYVAR="$(dirname "$(dirname $PWD)")"if you want 2nd parent directory

export MYVAR="$(dirname "$(dirname $PWD)")"如果你想要第二个父目录

回答by magoofromparis

ugly but efficient

丑陋但高效

function Parentdir()

{

{

local lookFor_ parent_ switch_ i_

lookFor_=""

#if it is not a file, we need the grand parent
[ -f "$lookFor_" ] || switch_="/.."

#length of search string
i_="${#lookFor_}"

#remove string one by one until it make sens for the system
while [ "$i_" -ge 0 ] && [ ! -d "${lookFor_:0:$i_}" ];
do
    let i_--
done

#get real path
parent_="$(realpath "${lookFor_:0:$i_}$switch_")" 

#done
echo "
lookFor_: 
{lookFor_:0:$i_}: ${lookFor_:0:$i_}
realpath {lookFor_:0:$i_}: $(realpath ${lookFor_:0:$i_})
parent_: $parent_ 
"

}

}

    lookFor_: /home/Om Namah Shivaya
{lookFor_:0:6}: /home/
realpath {lookFor_:0:6}: /home
parent_: /home 


lookFor_: /var/log
{lookFor_:0:8}: /var/log
realpath {lookFor_:0:8}: /UNIONFS/var/log
parent_: /UNIONFS/var 


lookFor_: /var/log/
{lookFor_:0:9}: /var/log/
realpath {lookFor_:0:9}: /UNIONFS/var/log
parent_: /UNIONFS/var 


lookFor_: /tmp//res.log/..
{lookFor_:0:6}: /tmp//
realpath {lookFor_:0:6}: /tmp
parent_: / 


lookFor_: /media/sdc8/../sdc8/Debian_Master//a
{lookFor_:0:35}: /media/sdc8/../sdc8/Debian_Master//
realpath {lookFor_:0:35}: /media/sdc8/Debian_Master
parent_: /media/sdc8 


lookFor_: /media/sdc8//Debian_Master/../Debian_Master/a
{lookFor_:0:44}: /media/sdc8//Debian_Master/../Debian_Master/
realpath {lookFor_:0:44}: /media/sdc8/Debian_Master
parent_: /media/sdc8 


lookFor_: /media/sdc8/Debian_Master/../Debian_Master/For_Debian
{lookFor_:0:53}: /media/sdc8/Debian_Master/../Debian_Master/For_Debian
realpath {lookFor_:0:53}: /media/sdc8/Debian_Master/For_Debian
parent_: /media/sdc8/Debian_Master 


lookFor_: /tmp/../res.log
{lookFor_:0:8}: /tmp/../
realpath {lookFor_:0:8}: /
parent_: /

回答by kris

Started from the idea/comment Charles Duffy?- Dec 17 '14 at 5:32 on the topic Get current directory name (without full path) in a Bash script

从想法/评论 Charles Duffy?- 2014 年 12 月 17 日 5:32 开始,主题为在 Bash 脚本中获取当前目录名称(无完整路径)

#!/bin/bash
#INFO : https://stackoverflow.com/questions/1371261/get-current-directory-name-without-full-path-in-a-bash-script
# comment : by Charles Duffy?- Dec 17 '14 at 5:32
# at the beginning :



declare -a dirName[]

function getDirNames(){
dirNr="$(  IFS=/ read -r -a dirs <<<"${dirTree}"; printf '%s\n' "$((${#dirs[@]} - 1))"  )"

for(( cnt=0 ; cnt < ${dirNr} ; cnt++))
  do
      dirName[$cnt]="$( IFS=/ read -r -a dirs <<<"$PWD"; printf '%s\n' "${dirs[${#dirs[@]} - $(( $cnt+1))]}"  )"
      #information – feedback
      echo "$cnt :  ${dirName[$cnt]}"
  done
}

dirTree=$PWD;
getDirNames;