Wenn ich einen Dateipfad habe wie ...
/home/smith/Desktop/Test
/home/smith/Desktop/Test/
Wie ändere ich die Zeichenfolge, damit es das übergeordnete Verzeichnis ist?
z.B.
/home/smith/Desktop
/home/smith/Desktop/
dir=/home/smith/Desktop/Test
parentdir="$(dirname "$dir")"
Funktioniert auch, wenn es einen nachgestellten Schrägstrich gibt.
... aber was ist "gesehen hier " ist kaputt. Hier ist der Fix:
> pwd
/home/me
> x='Om Namah Shivaya'
> mkdir "$x" && cd "$x"
/home/me/Om Namah Shivaya
> parentdir="$(dirname "$(pwd)")"
> echo $parentdir
/home/me
Natürlich wird das übergeordnete Verzeichnis durch einfaches Anhängen des Punkt-Dateinamens angegeben:
/home/smith/Desktop/Test/.. # unresolved path
Sie müssen jedoch den aufgelösten Pfad (einen absoluten Pfad ohne Punkt-Punkt-Pfadkomponenten) haben:
/home/smith/Desktop # resolved path
Das Problem mit den ersten Antworten, die dirname
verwenden, besteht darin, dass sie nicht funktionieren, wenn Sie einen Pfad mit Punktpunkten eingeben:
$ dir=~/Library/../Desktop/../..
$ parentdir="$(dirname "$dir")"
$ echo $parentdir
/Users/username/Library/../Desktop/.. # not fully resolved
Das ist mächtiger :
dir=/home/smith/Desktop/Test
parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`
Sie können es /home/smith/Desktop/Test/..
, aber auch komplexere Pfade wie:
$ dir=~/Library/../Desktop/../..
$ parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`
$ echo $parentdir
/Users # the fully resolved path!
Wenn /home/smith/Desktop/Test/../
das ist, was Sie wollen:
dirname 'path/to/child/dir'
wie gesehen hier .
Verwenden Sie einfach echo $(cd ../ && pwd)
, während Sie in dem Verzeichnis arbeiten, dessen übergeordnetes Verzeichnis Sie herausfinden möchten. Diese Kette hat auch den zusätzlichen Vorteil, dass keine nachlaufenden Schrägstriche vorhanden sind.
Ich mag sehr kurzen, klaren, garantierten Code. Bonuspunkt, wenn kein externes Programm ausgeführt wird, da der Tag, an dem Sie eine große Anzahl von Einträgen verarbeiten müssen, deutlich schneller ist.
Sie sind sich nicht sicher, welche Garantien Sie haben und wollen, und bieten Sie trotzdem an.
Wenn Sie Garantien haben, können Sie dies mit sehr kurzem Code tun. Die Idee ist, die Bash-Textsubstitutionsfunktion zu verwenden, um den letzten Schrägstrich und alles, was folgt, abzuschneiden.
Antwort von einfachen bis komplexeren Fällen der ursprünglichen Frage.
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
Abhängig davon, ob Sie absolute Pfade benötigen, möchten Sie möglicherweise einen zusätzlichen Schritt tun:
child='/home/smith/Desktop/Test/'
parent=$(dirname "$child")
abs_parent=$(realpath "$parent")
Gestartet von der Idee/Kommentar Charles Duffy - 17. Dezember 14 um 5:32 Uhr zum Thema Aktuellen Verzeichnisnamen (ohne vollständigen Pfad) in einem Bash-Skript abrufen
#!/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;
verwenden Sie folgendes: export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")"
, wenn Sie das vierte übergeordnete Verzeichnis möchten
export MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")"
wenn Sie ein drittes übergeordnetes Verzeichnis wünschen
export MYVAR="$(dirname "$(dirname $PWD)")"
wenn Sie das zweite übergeordnete Verzeichnis wünschen
hässlich aber effizient
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_: /