簡體   English   中英

在 Bash 中獲取目錄的父級

[英]Getting the parent of a directory in Bash

如果我有一個文件路徑,例如...

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

如何更改字符串,使其成為父目錄?

例如

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

如果有斜線也可以工作。

顯然,父目錄是通過簡單地附加點文件名給出的:

/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!
 

注意:使用builtin確保不會調用用戶定義的cd函數變體,而是調用沒有輸出的默認實用程序形式。

在您要查找其父目錄的目錄中工作時,只需使用echo $(cd ../ && pwd)即可。 該鏈還具有沒有尾部斜杠的額外好處。

...但是“在這里看到的”被破壞了。 這是修復:

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

另一個答案的動機

我喜歡非常簡短、清晰、有保證的代碼。 如果它不運行外部程序,則加分點,因為您需要處理大量條目的那一天,它會明顯更快。

原則

不確定您擁有和想要什么保證,所以無論如何都要提供。

如果你有保證,你可以用非常短的代碼來做到這一點。 這個想法是使用 bash 文本替換功能來剪切最后一個斜杠以及后面的任何內容。

回答原始問題的簡單到更復雜的情況。

如果路徑保證結束時沒有任何斜線(進出)

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

如果路徑保證以一個斜線結尾(進出)

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

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

dirname 'path/to/child/dir'

如此所見。

如果您只需要父目錄的名稱:

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

根據您是否需要絕對路徑,您可能需要采取額外的步驟:

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

使用這個: export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")"如果你想要第四個父目錄

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

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

丑陋但高效

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_: /

從想法/評論 Charles Duffy - 2014 年 12 月 17 日 5:32 開始,主題為Get current directory name (without full path) in a Bash script

#!/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 ../

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM