Wenn ich einen Dateipfad habe wie ...
/home/smith/Desktop/Test
/home/smith/Desktop/Test/
Wie ändere ich die Zeichenfolge so, dass sie das übergeordnete Verzeichnis ist?
z.B
/home/smith/Desktop
/home/smith/Desktop/
Wenn ich einen Dateipfad habe wie ...
/home/smith/Desktop/Test
/home/smith/Desktop/Test/
Wie ändere ich die Zeichenfolge so, dass sie das übergeordnete Verzeichnis ist?
z.B
/home/smith/Desktop
/home/smith/Desktop/
Antworten:
dir=/home/smith/Desktop/Test
parentdir="$(dirname "$dir")"
Funktioniert auch, wenn es einen abschließenden Schrägstrich gibt.
parentdir=$(dirname `pwd`)
... aber was " hier gesehen " ist kaputt. Hier ist das Update:
> pwd
/home/me
> x='Om Namah Shivaya'
> mkdir "$x" && cd "$x"
/home/me/Om Namah Shivaya
> parentdir="$(dirname "$(pwd)")"
> echo $parentdir
/home/me
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 sie keine nachlaufenden Schrägstriche aufweist.
echo
hier nicht.
Das übergeordnete Verzeichnis wird eindeutig durch einfaches Anhängen des Punkt-Punkt-Dateinamens angegeben:
/home/smith/Desktop/Test/.. # unresolved path
Sie müssen jedoch den aufgelösten Pfad (einen absoluten Pfad ohne Punkt-Punkt-Pfad-Komponenten) möchten :
/home/smith/Desktop # resolved path
Das Problem mit den häufigsten Antworten dirname
ist, 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 füttern /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!
BEARBEITEN: Wenn es nicht funktioniert, überprüfen Sie, ob Sie cd
nicht geändert wurden, wie es manchmal üblich ist.
$ which cd
cd is a function #cd was modified to print extra info, so use "builtin cd" to override
cd ()
{
builtin cd "$@";
ls -FGAhp
}
...
eval
ist NICHT großartig, wenn die Möglichkeit besteht, Benutzereingaben zu analysieren, die Sie an einen Ort bringen könnten, an dem Sie keine schlechten Dinge erwarten oder gegen Ihr System ausführen. Können Sie pushd $dir 2>&1 >/dev/null && pwd && popd 2>&1 >/dev/null
anstelle der verwenden eval
?
eval
überhaupt nicht: tun Sie es einfach parentdir=$(cd -- "$dir" && pwd)
. Da das cd
in einer Subshell ausgeführt wird, müssen Sie nicht dorthin zurückkehren, cd
wo wir waren. Das --
ist hier für den Fall, dass die Erweiterung von $dir
mit einem Bindestrich beginnt. Das &&
soll nur verhindern parentdir
, dass ein nicht leerer Inhalt vorhanden ist, wenn der cd
nicht erfolgreich war.
Ich mag sehr kurzen, klaren, garantierten Code. Bonuspunkt, wenn kein externes Programm ausgeführt wird, da es an dem Tag, an dem Sie eine große Anzahl von Einträgen verarbeiten müssen, spürbar schneller ist.
Ich bin mir nicht sicher, welche Garantien Sie haben und wollen, also bieten Sie es trotzdem an.
Wenn Sie Garantien haben, können Sie dies mit sehr kurzem Code tun. Die Idee ist, die Bash-Textersetzungsfunktion zu verwenden, um den letzten Schrägstrich und was auch immer folgt, zu schneiden.
Beantworten Sie einfache bis komplexere Fälle 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
${BASH_SOURCE[0]}
wäre der vollständige Pfad zum Skript, wenn es nicht über source
oder bezogen würde .
.
Wenn /home/smith/Desktop/Test/../
es das ist, was Sie wollen:
dirname 'path/to/child/dir'
wie hier gesehen .
bash: dirname 'Test': syntax error: invalid arithmetic operator (error token is "'Test'")
. Verknüpfter Code ist auch falsch.
dirname Test
aus dem Verzeichnis zu laufen Test
ist in.
Je nachdem, ob Sie absolute Pfade benötigen, möchten Sie möglicherweise einen zusätzlichen Schritt ausführen:
child='/home/smith/Desktop/Test/'
parent=$(dirname "$child")
abs_parent=$(realpath "$parent")
Verwenden Sie dies: export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")"
Wenn Sie das 4. übergeordnete Verzeichnis möchten
export MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")"
Wenn Sie das 3. übergeordnete Verzeichnis möchten
export MYVAR="$(dirname "$(dirname $PWD)")"
Wenn Sie das 2. übergeordnete Verzeichnis möchten
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_: /
Ausgehend von der Idee / dem 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 : /programming/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;
Wenn Sie aus irgendeinem Grund daran interessiert sind, durch eine bestimmte Anzahl von Verzeichnissen zu navigieren, können Sie auch Folgendes tun : nth_path=$(cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd ../../../ && pwd)
. Dies würde 3 Elternverzeichnisse aufgeben
..
' verwenden, aber vielleicht ist das nicht ganz das, was Sie sich vorgestellt haben.