Jak zdobyć ostatnią część dirname w Bash

81

Załóżmy, że mam plik /from/here/to/there.txti tozamiast /from/here/totego chcę uzyskać tylko ostatnią część jego nazwy katalogu , co mam zrobić?

bakłażan
źródło

Odpowiedzi:

120

Możesz użyć, basenamenawet jeśli nie jest to plik. Usuń nazwę pliku za pomocą dirname, a następnie użyj, basenameaby pobrać ostatni element ciągu:

dir="/from/here/to/there.txt"
dir="$(dirname $dir)"   # Returns "/from/here/to"
dir="$(basename $dir)"  # Returns just "to"
David W.
źródło
2
polecenie '$ dir = "$ (dirname $ dir)"' nie działa dla mnie, ale 'dir = "$ (dirname $ dir)"' działa dobrze.
Nikolai Saiko
2
Nie powinienem był mieć dolara przed, dirkiedy go ustawiam.
David W.
26

Przeciwieństwem dirnamejest basename:

basename "$(dirname "/from/here/to/there.txt")"
ten inny facet
źródło
23

Korzystanie z bashfunkcji tekstowych:

$ s="/from/here/to/there.txt"
$ s="${s%/*}" && echo "${s##*/}"
to
jaypal singh
źródło
9

Używając rozszerzenia parametrów Bash , możesz to zrobić:

path="/from/here/to/there.txt"
dir="${path%/*}"       # sets dir      to '/from/here/to' (equivalent of dirname)
last_dir="${dir##*/}"  # sets last_dir to 'to' (equivalent of basename)

Jest to bardziej wydajne, ponieważ nie są używane żadne polecenia zewnętrzne.

codeforester
źródło
Właśnie to przetestowałem. Oto moje wyniki na FreeBSD: Kod: #! / Bin / sh cd / var / svn / repos path = "$ 1" echo "$ {path}" dir = "$ {path% / *}" echo "$ {dir } "faktyczna =" $ {katalog ## * /} "echo" $ {rzeczywista} "----------------------------- ----------- Wyniki: $ ./makerepo.sh / var / test / var / test / var var $ ------------------- ----------------- Zawieść! Przepraszam. Wydawało się, że to dobra metoda, ale nie jest to poprawna odpowiedź.
Richard Robertson
4

Czysty sposób BASH:

s="/from/here/to/there.txt"
[[ "$s" =~ ([^/]+)/[^/]+$ ]] && echo "${BASH_REMATCH[1]}"
to
anubhava
źródło
2
Nie zadziała, jeśli plik nie ma kropki .. Nie zadziała, jeśli katalog ma kropkę .. Zachowaj prostotę i użyj ukośnika /jako separatora.
alvits
1
Wielkie dzięki @Akshay
anubhava
3

Można awkto zrobić:

awk -F'/' '{print $(NF-1)}' <<< "/from/here/to/there.txt"

Wyjaśnienie:

  • -F'/' ustawia separator pól na „/”
  • wydrukuj przedostatnie pole $(NF-1)
  • <<<używa wszystkiego po nim jako standardowego wejścia ( wyjaśnienie wiki )
csiu
źródło
2

Jeszcze jeden sposób

IFS=/ read -ra x <<<"/from/here/to/there.txt" && printf "%s\n" "${x[-2]}"
iruvar
źródło
Prostsze w użyciu: printf "%s\n" "${x[-2]}".
gniourf_gniourf
1

To pytanie jest podobne do TEGO .

Aby rozwiązać, co możesz zrobić:

DirPath="/from/here/to/there.txt"
DirPath="$(dirname $DirPath)"
DirPath="$(basename $DirPath)"

echo "$DirPath"

Jak powiedział mój przyjaciel, jest to również możliwe:

basename `dirname "/from/here/to/there.txt"`

Aby uzyskać jakąkolwiek część swojej ścieżki, możesz:

echo "/from/here/to/there.txt" | awk -F/ '{ print $2 }'
OR
echo "/from/here/to/there.txt" | awk -F/ '{ print $3 }'
OR
etc
MLSC
źródło
1

Najwyższa odpowiedź jest absolutnie poprawna dla zadanego pytania. W bardziej ogólnym przypadku, w którym potrzebny katalog znajduje się w środku długiej ścieżki, takie podejście prowadzi do trudnego do odczytania kodu. Na przykład :

dir="/very/long/path/where/THIS/needs/to/be/extracted/text.txt"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(basename $dir)"

W tym przypadku można użyć:

IFS=/; set -- "/very/long/path/where/THIS/needs/to/be/extracted/text.txt"; set $1; echo $6
THIS
yashma
źródło