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

81

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

яйцо
источник

Ответы:

120

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

dir="/from/here/to/there.txt"
dir="$(dirname $dir)"   # Returns "/from/here/to"
dir="$(basename $dir)"  # Returns just "to"
Дэвид В.
источник
2
команда '$ dir = "$ (dirname $ dir)"' у меня не работает, но 'dir = "$ (dirname $ dir)"' работает нормально.
Николай Сайко,
2
Я не должен был иметь перед собой доллар, dirкогда устанавливаю его.
Дэвид В.
26

Противоположность dirnameIS basename:

basename "$(dirname "/from/here/to/there.txt")"
тот другой парень
источник
23

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

$ s="/from/here/to/there.txt"
$ s="${s%/*}" && echo "${s##*/}"
to
Джайпал Сингх
источник
9

Используя расширение параметра 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)

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

Codeforester
источник
Я только что это проверил. На FreeBSD вот мои результаты: Код: #! / Bin / sh cd / var / svn / repos path = "$ 1" echo "$ {path}" dir = "$ {path% / *}" echo "$ {dir } "actual =" $ {dir ## * /} "echo" $ {actual} "----------------------------- ----------- Результаты: $ ./makerepo.sh / var / test / var / test / var var $ ------------------- ----------------- Потерпеть поражение! Сожалею. Казалось, хороший метод, но неправильный ответ.
Ричард Робертсон
4

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

s="/from/here/to/there.txt"
[[ "$s" =~ ([^/]+)/[^/]+$ ]] && echo "${BASH_REMATCH[1]}"
to
анубхава
источник
2
Не будет работать, если в файле нет точки .. Не будет работать, если в каталоге есть точка .. Сделайте это простым и используйте косую черту в /качестве разделителя.
alvits
1
Большое спасибо @Akshay
anubhava
3

Один из awkспособов сделать это:

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

Пояснение:

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

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

IFS=/ read -ra x <<<"/from/here/to/there.txt" && printf "%s\n" "${x[-2]}"
Ирувар
источник
Simpler использовать: printf "%s\n" "${x[-2]}".
gniourf_gniourf
1

Этот вопрос что - то вроде этого .

Для решения этого вы можете:

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
MLSC
источник
1

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

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
Яшма
источник