Как получить последнюю часть имени каталога в Bash

Предположим, у меня есть файл /from/here/to/there.txt, и я хочу получить только последнюю часть его имени каталога to вместо /from/here/to, что мне делать?


person eggplantelf    schedule 18.04.2014    source источник


Ответы (9)


Вы можете использовать basename, даже если это не файл. Удалите имя файла, используя dirname, затем используйте basename, чтобы получить последний элемент строки:

dir="/from/here/to/there.txt"
dir="$(dirname $dir)"   # Returns "/from/here/to"
dir="$(basename $dir)"  # Returns just "to"
person David W.    schedule 18.04.2014
comment
команда «$dir=$(dirname $dir)» у меня не работает, но «dir=$(dirname $dir)» работает нормально. - person Nikolai Saiko; 24.03.2015
comment
У меня не должно было быть доллара перед dir, когда я его устанавливал. - person David W.; 24.03.2015

Противоположностью dirname является basename:

basename "$(dirname "/from/here/to/there.txt")"
person that other guy    schedule 18.04.2014

Использование bash строковых функций:

$ s="/from/here/to/there.txt"
$ s="${s%/*}" && echo "${s##*/}"
to
person jaypal singh    schedule 18.04.2014

Используя Bash расширение параметров, вы можете сделать это :

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)

Это более эффективно, поскольку внешние команды не используются.

person codeforester    schedule 04.06.2017
comment
Я только что проверил это. Во FreeBSD вот мои результаты: Код: #!/bin/sh cd /var/svn/repos path=$1 echo ${path} dir=${path%/*} echo ${dir} fact=${dir# #*/} echo ${actual} ---------------------------------------- Результаты : $ ./makerepo.sh /var/test /var/test /var var $ ---------------------------------------------- ----- Потерпеть неудачу! Извиняюсь. Казалось хорошим методом, но не правильным ответом. - person Richard Robertson; 18.11.2017

Чистый способ BASH:

s="/from/here/to/there.txt"
[[ "$s" =~ ([^/]+)/[^/]+$ ]] && echo "${BASH_REMATCH[1]}"
to
person anubhava    schedule 18.04.2014
comment
Не будет работать, если в файле нет точки .. Не будет работать, если в каталоге есть точка .. Будьте проще и используйте косую черту / в качестве разделителя. - person alvits; 19.04.2014

awk способ сделать это:

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

Пояснение:

  • -F'/' устанавливает разделитель полей как "/"
  • напечатать предпоследнее поле $(NF-1)
  • <<< использует все после него в качестве стандартного ввода (объяснение вики)
person csiu    schedule 19.04.2014

Еще один способ

IFS=/ read -ra x <<<"/from/here/to/there.txt" && printf "%s\n" "${x[-2]}"
person iruvar    schedule 18.04.2014
comment
Проще использовать: printf "%s\n" "${x[-2]}". - person gniourf_gniourf; 19.04.2014

Этот вопрос похож на THIS.

Для решения, что вы можете сделать:

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

echo "$DirPath"

Как сказал мой друг, это тоже возможно:

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

Чтобы получить любую часть вашего пути, вы можете сделать:

echo "/from/here/to/there.txt" | awk -F/ '{ print $2 }'
OR
echo "/from/here/to/there.txt" | awk -F/ '{ print $3 }'
OR
etc
person MLSC    schedule 19.04.2014

Верхний ответ абсолютно правильный для заданного вопроса. В более общем случае, когда нужный каталог находится в середине длинного пути, такой подход приводит к трудночитаемому коду. Например :

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)"

В этом случае можно использовать:

IFS=/; set -- "/very/long/path/where/THIS/needs/to/be/extracted/text.txt"; set $1; echo $6
THIS
person yashma    schedule 13.05.2020