Dateiverzeichnispfad vom Dateipfad abrufen


400

Wenn in Bash, wenn VAR="/home/me/mydir/file.c", wie komme ich "/home/me/mydir"?

Antworten:


648

dirnameund basenamesind die Tools, nach denen Sie suchen, um Pfadkomponenten zu extrahieren:

$ VAR=/home/me/mydir/file.c

$ DIR=$(dirname "${VAR}")

$ echo "${DIR}"
/home/me/mydir

$ basename "${VAR}"
file.c

Sie sind nicht interne Bash Befehle , aber sie sind Teil des POSIX - Standard (siehe dirname, basename) und sollte so auf die überwiegende Mehrheit der Systeme zur Verfügung , die Bash laufen wird.


4
Warum die Verwendung von Klammern um die Variablennamen und nicht "$ VAR" zum Beispiel?
user658182

1
stackoverflow.com/questions/8748831/… beantwortet die obige Frage.
user658182

1
@ user658182 In diesem speziellen Beispiel geschieht dies aus Gewohnheit und nicht aus Notwendigkeit.
Verlassener Wagen

95
$ export VAR=/home/me/mydir/file.c
$ export DIR=${VAR%/*}
$ echo "${DIR}"
/home/me/mydir

$ echo "${VAR##*/}"
file.c

Um die Abhängigkeit von basenameund zu vermeidendirname


3
Da beide Teil von POSIX sind, sollte eine Abhängigkeit kein Problem sein.
Orkoden

1
Orkoden, du hast recht. Mit meiner Antwort möchte ich zeigen, dass keine Verpflichtung besteht, zwei zusätzliche Prozesse auszuführen. bash ist für den Anwendungsfall autark.
Emmanuel Devaux

2
Ich verwende Emmanuels Methode, weil ich entweder eine Datei oder einen Ordnernamen übergeben und dann den Ordnerpfad berechnen möchte. Die Verwendung dieses regulären Ausdrucks ist das Richtige, während die Funktion dirname den übergeordneten Ordner zurückgab, wenn ich einen Ordner eingab.
AnneTheAgile

8
Wenn jedoch in $ VAR keine Pfadinformationen vorhanden sind, erzeugt $ {VAR% / *} / test einen unerwarteten Wert gleich $ VAR / test, während $ (dirname $ VAR) den vorhersehbareren und angemesseneren Wert von ./test erzeugt. Dies ist eine große Sache, da der erstere versucht, den Dateinamen als Verzeichnis zu behandeln, während der letztere in Ordnung ist.
Davemyron

19

Wenn Sie nur den Dateinamen oder den relativen Pfad haben, dirnamehilft dies nicht. Für mich war die Antwort letztendlich readlink.

fname='txtfile'    
echo $(dirname "$fname")                # output: .
echo $(readlink -f "$fname")            # output: /home/me/work/txtfile

Sie können dann beide kombinieren, um nur das Verzeichnis zu erhalten.

echo $(dirname $(readlink -f "$fname")) # output: /home/me/work

1
Wenn nicht mehr als eine Pfadkomponente vorhanden war, sollten Sie den readlink -m "$fname"angegebenen Namen rekursiv
kanonisieren

7

Wenn Sie möchten, dass Zieldateien ein symbolischer Link sind, können Sie dies zunächst überprüfen und die Originaldatei abrufen. Die folgende if-Klausel kann Ihnen helfen.

if [ -h $file ]
then
 base=$(dirname $(readlink $file))
else
 base=$(dirname $file)
fi

5

Ich habe damit gespielt und mir eine Alternative ausgedacht.

$ VAR=/home/me/mydir/file.c

$ DIR=`echo $VAR |xargs dirname`

$ echo $DIR
/home/me/mydir

Der Teil, den ich mochte, war, dass es einfach war, die Sicherung des Baums zu erweitern:

$ DIR=`echo $VAR |xargs dirname |xargs dirname |xargs dirname`

$ echo $DIR
/home

1

Hier ist ein Skript, das ich zum rekursiven Trimmen verwendet habe. Ersetzen Sie $ 1 natürlich durch das gewünschte Verzeichnis.

BASEDIR="$1"
IFS=$'\n'
cd $BASEDIR
 for f in $(find . -type f -name ' *')
 do 
    DIR=$(dirname "$f")
    DIR=${DIR:1}
    cd $BASEDIR$DIR
    rename 's/^ *//' *
 done

0

Zuerst habe ich durch /Leerzeichen ( ) ersetzt. Dann habe ich alle Zeichen vor einem leeren Leerzeichen gelöscht ( ). Am Ende habe ich das erste Zeichen entfernt, das Leerzeichen ist ( ).

$ VAR="/home/me/mydir/file.c"

$ echo $VAR | tr '/' ' ' | sed 's/^.* / /' | cut -c2-
file.c

0
HERE=$(cd $(dirname $BASH_SOURCE) && pwd)

wo Sie den vollständigen Pfad mit new_path = erhalten $(dirname ${BASH_SOURCE[0]}). Sie ändern das aktuelle Verzeichnis mit cd new_path und führen es aus pwd, um den vollständigen Pfad zum aktuellen Verzeichnis abzurufen .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.