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

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

我如何改变字符串,使它将是父目录?

e.g.

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

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

dirname 'path/to/child/dir'

如图所示。


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

如果后面有斜杠,也可以。


...但“这里看到的”是坏的。下面是解决方案:

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

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

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

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

出口myvar# = " $(目录名“$(目录名(目录名$ PWD)美元)”)” 如果你想要第三个父目录

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


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


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

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

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

/home/smith/Desktop             # resolved path

使用dirname的顶部答案的问题是,当你输入一个带有点号的路径时,它们不起作用:

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

这个更强大:

dir=/home/smith/Desktop/Test
parentdir=$(builtin cd $dir; pwd)

你可以在/home/smith/Desktop/Test/..,但也有更复杂的路径,比如:

$ dir=~/Library/../Desktop/../..
$ parentdir=$(builtin cd $dir; pwd)
$ echo $parentdir
/Users                                  # the fully resolved path!
 

注意:使用内置确保不会调用用户定义的cd函数变体,而是调用没有输出的默认实用程序形式。


丑陋但高效

function Parentdir()

{

local lookFor_ parent_ switch_ i_

lookFor_="$1"

#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_: $1
{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_: /

另一个答案的动机

我喜欢非常简短、清晰、有保证的代码。如果它不运行外部程序,它的好处是,因为有一天你需要处理大量的输入,它会明显更快。

原则

不确定你有什么保证,想要什么,所以还是提供吧。

如果你有保证,你可以用很短的代码完成它。其思想是使用bash文本替换特性来删除最后一个斜杠和后面的任何内容。

回答从简单到较复杂情况下的原题。

如果路径保证结尾没有任何斜杠(in和out)

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

如果path保证以一个斜杠结尾(in和out)

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

如果输入路径可能以零或一个斜杠(而不是多个)结束,而您希望输出路径以不带斜杠结束

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

如果输入路径可能有许多多余的斜杠,而您希望输出路径结束时不带斜杠

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

从Charles Duffy - Dec 17 '14 at 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;

如果出于某种原因,你想要浏览特定数量的目录,你也可以这样做:nth_path=$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && & cd ../../../ && pwd)。这将提供3个父目录


这个会被放到父文件夹中

cd ../

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

parent_dir_name=$(basename $(dirname $PWD))