result=${PWD##*/} # to assign to a variable
printf '%s\n' "${PWD##*/}" # to print to stdout
# ...more robust than echo for unusual names
# (consider a directory named -e or -n)
printf '%q\n' "${PWD##*/}" # to print to stdout, quoted for use as shell input
# ...useful to make hidden characters readable.
Обратите внимание, что если вы применяете эту технику в других обстоятельствах (нет PWD, но в какой-то другой переменной, содержащей имя каталога), вам может потребоваться обрезать любые завершающие косые черты. Ниже используется поддержка extglob в bash для работы даже с несколькими конечными слешами :
dirname=/path/to/somewhere//
shopt -s extglob # enable +(...) glob syntax
result=${dirname%%+(/)}# trim however many trailing slashes exist
result=${result##*/} # remove everything before the last / that still remains
printf '%s\n'"$result"
Альтернативно, без extglob:
dirname="/path/to/somewhere//"
result="${dirname%"${dirname##*[!/]}"}" # extglob-free multi-trailing-/ trim
result="${result##*/}"# remove everything before the last /
@Mr_Chimp первый - это операция расширения параметра, которая обрезает остальную часть каталога, чтобы предоставить только базовое имя. В моем ответе есть ссылка на документацию по расширению параметров; не стесняйтесь следовать этому, если у вас есть какие-либо вопросы.
Чарльз Даффи
24
@stefgosselin $PWD- это имя встроенной переменной bash; все встроенные имена переменных указаны заглавными буквами (чтобы отличать их от локальных переменных, которые всегда должны иметь хотя бы один символ нижнего регистра). result=${PWD#*/}делает не вычисляться /full/path/to/directory; вместо этого он удаляет только первый элемент, делая его path/to/directory; использование двух #символов делает сопоставление шаблона жадным, сопоставляя столько символов, сколько возможно. Прочитайте страницу расширения параметров, связанную в ответе, для получения дополнительной информации.
Чарльз Даффи
5
Обратите внимание, что выходные данные from pwdне всегда совпадают со значением $PWD, из-за сложностей, возникающих при cdпрохождении через символические ссылки, имеет ли bash установленный -o physicalпараметр и так далее. Раньше это было особенно неприятно при работе с автоматически монтируемыми каталогами, когда запись физического пути вместо логического давала бы путь, который, в случае его использования, позволял бы автомонтированию самопроизвольно отключать каталог, который он использовал.
Алекс Норт-Киз
3
Ницца! Кто-то должен написать книгу для старых ребят из Borne, таких как я. Может быть, есть один там? У старого системного администратора может быть какая-то шумиха, говорящая что-то вроде: «В свое время мы только shи, cshесли вы хотели, чтобы клавиша Backspace работала, вам нужно было прочитать всю sttyсправочную страницу, и нам понравилось!»
Разве это не цель basenameпрограммы? Что не так с этим ответом, кроме пропущенных кавычек?
Nacht - Восстановить Монику
11
@Nacht basenameдействительно внешняя программа , которая делает правильно, но работает любую внешнюю программу для вещи Баша может делать вне коробки , используя только встроенные функции глупо, подвергаясь влиянием на производительность ( fork(), execve(), wait()и т.д.) для нет причин.
Чарльз Даффи
3
... кроме того, мои возражения basenameздесь не применимы dirname, потому что dirnameимеет функциональность, ${PWD##*/}которой нет - например, преобразование строки без косой черты .. Таким образом, хотя использование dirnameв качестве внешнего инструмента приводит к снижению производительности, оно также имеет функциональность, которая помогает компенсировать его.
Чарльз Даффи
4
@LouisMaddox, немного кибитцинга: functionключевое слово несовместимо с POSIX, не добавляя никакого значения к стандартизированному синтаксису, а отсутствие кавычек может привести к ошибкам в именах каталогов с пробелами. wdexec() { "./$(basename "$PWD")"; }может быть предпочтительной альтернативой.
Чарльз Даффи
28
Конечно, использование basenameменее «эффективно». Но это, вероятно, более эффективно с точки зрения производительности разработчика, потому что его легко запомнить по сравнению с уродливым синтаксисом bash. Так что, если вы помните это, пойти на это. В противном случае basenameработает так же хорошо. Кто-нибудь когда-нибудь должен был улучшить «производительность» bash-скрипта и сделать его более эффективным?
@jocap ... за исключением того, что использование echo там без указания аргумента неверно . Если имя каталога содержит несколько пробелов или символ табуляции, оно будет свернуто в один пробел; если он имеет подстановочный знак, он будет расширен. Правильное использование будет echo "${PWD##*/}".
Чарльз Даффи
9
@jocap ... также я не уверен, что "эхо" на самом деле является законной частью ответа. Вопрос заключался в том, как получить ответ, а не в том, как напечатать ответ; например, если бы целью было присвоить ее переменной, это name=${PWD##*/}было бы правильно и name=$(echo "${PWD##*/}")неправильно (в смысле ненужной неэффективности).
Чарльз Даффи
24
Вы можете использовать комбинацию pwd и basename. Например
Пожалуйста, не надо. Обратные метки создают подоболочку (таким образом, операцию разветвления) - и в этом случае вы используете их дважды ! [В качестве дополнительного, хотя и стилистического, смысла - имена переменных должны быть в нижнем регистре, если вы не экспортируете их в среду или они не являются специальным, зарезервированным регистром].
Чарльз Даффи
11
и в качестве второго стиля придирки следует заменить на $ (). все еще вилки, но более удобочитаемые и с меньшими затратами.
Джереми Уолл
1
По соглашению переменные среды (PATH, EDITOR, SHELL, ...) и переменные внутренней оболочки (BASH_VERSION, RANDOM, ...) полностью пишутся с заглавной буквы. Все остальные имена переменных должны быть строчными. Поскольку имена переменных чувствительны к регистру, это соглашение позволяет избежать случайного переопределения переменных среды и внутренних переменных.
Рани Албег Вайн
2
Зависит от конвенции. Можно утверждать, что все переменные оболочки являются переменными среды (в зависимости от оболочки), и поэтому все переменные оболочки должны быть в заглавных буквах. Кто-то еще может поспорить, основываясь на области видимости: глобальные переменные - это заглавные буквы, а локальные переменные - строчные, и все они глобальные. Еще один может поспорить, что создание переменных в верхнем регистре добавляет дополнительный уровень контраста с командами, засоряющими сценарии оболочки, которые также представляют собой короткие строчные, но значимые слова. Я могу или не могу / согласиться / с любым из этих аргументов, но я видел все три в использовании. :)
Я бы не рекомендовал, потому что кажется, что он получает некоторую информацию о цвете, тогда как pwd | xargs basenameэто не так… вероятно, это не так важно, но другой ответ проще и более последовательный в разных средах
davidhq
8
Мне нравится выбранный ответ (Чарльз Даффи), но будьте осторожны, если вы находитесь в директории с символическими ссылками и хотите указать имя целевой директории. К сожалению, я не думаю, что это можно сделать в выражении расширения с одним параметром, возможно, я ошибаюсь. Это должно работать:
К вашему сведению, ${PWD##*/}это POSIX sh - каждый современный / bin / sh (включая dash, ash и т. Д.) Поддерживает его; чтобы поразить настоящую Борн на недавнем боксе, вам нужно будет использовать слегка устаревшую систему Solaris. Помимо этого - echo "$PWD"; пропуск кавычек приводит к ошибкам (если в имени каталога есть пробелы, подстановочные знаки и т. д.).
Чарльз Даффи
1
Да, я использовал старую систему Solaris. Я обновил команду для использования кавычек.
как ни странно ? просто шучу, но другие гораздо короче и их легче запомнить
codewandler
Это довольно забавно = P До этого не слышал о $ IFS (внутренний разделитель полей). мой bash был слишком стар, но можете проверить его здесь: jdoodle.com/test-bash-shell-script-online
Стэн Курджиль
5
Использование:
basename "$PWD"
ИЛИ
IFS=/
var=($PWD)
echo ${var[-1]}
Верните внутренний разделитель имен файлов (IFS) обратно в пробел.
Требуется больше кавычек, чтобы быть правильными - как есть, выходные данные pwdразделяются на строки и расширяются глобально, прежде чем будут переданы basename.
Чарльз Даффи
Таким образом, basename "$(pwd)"- хотя это очень неэффективно по сравнению с just basename "$PWD", что само по себе неэффективно по сравнению с использованием раскрытия параметра вместо вызова basenameвообще.
Это во всех отношениях худшая версия ответа, ранее предоставленного Аркадием ( stackoverflow.com/a/1371267/14122 ): xargsФормула неэффективна и содержит ошибки, когда имена каталогов содержат буквенные символы новой строки или символы кавычек, а вторая формулировка вызывает pwdкоманду в подоболочке, вместо того, чтобы получить тот же результат через встроенное расширение переменной.
Чарльз Даффи
@CharlesDuffy Тем не менее это правильный и практичный ответ на вопрос.
Бахф
1
Если вы хотите видеть только текущий каталог в области приглашения bash, вы можете отредактировать .bashrcфайл в ~. Изменение \wк \Wв строке:
Вы можете использовать утилиту basename, которая удаляет любой префикс, заканчивающийся на / и суффикс (если присутствует в строке) из строки, и выводит результат на стандартный вывод.
К вашему сведению, это не входит в мой дистрибутив Ubuntu.
Katastic Voyage
@KatasticVoyage, он есть в Ubuntu, он просто называется basenameтам. Обычно gbasenameон вызывается только на MacOS и других платформах, которые в противном случае поставляются с базовым именем не-GNU.
Чарльз Даффи
-1
Следующие команды приведут к печати вашего текущего рабочего каталога в bash-скрипте.
(1) Я не уверен, где мы гарантируем, что список аргументов таков, что $1будет содержать текущий рабочий каталог. (2) pushdи popdне служит никакой цели здесь , потому что что - то внутри обратных кавычек делаются в субоболочке - поэтому он не может повлиять на каталог родительской оболочки, чтобы начать с. (3) Использование "$(cd "$1"; pwd)"будет более читабельным и устойчивым к именам каталогов с пробелами.
Ответы:
Нет необходимости в базовом имени, и особенно нет необходимости в подоболочке, выполняющей pwd (которая добавляет дополнительную и дорогую операцию fork ); оболочка может сделать это внутренне, используя расширение параметров :
Обратите внимание, что если вы применяете эту технику в других обстоятельствах (нет
PWD
, но в какой-то другой переменной, содержащей имя каталога), вам может потребоваться обрезать любые завершающие косые черты. Ниже используется поддержка extglob в bash для работы даже с несколькими конечными слешами :Альтернативно, без
extglob
:источник
$PWD
- это имя встроенной переменной bash; все встроенные имена переменных указаны заглавными буквами (чтобы отличать их от локальных переменных, которые всегда должны иметь хотя бы один символ нижнего регистра).result=${PWD#*/}
делает не вычисляться/full/path/to/directory
; вместо этого он удаляет только первый элемент, делая егоpath/to/directory
; использование двух#
символов делает сопоставление шаблона жадным, сопоставляя столько символов, сколько возможно. Прочитайте страницу расширения параметров, связанную в ответе, для получения дополнительной информации.pwd
не всегда совпадают со значением$PWD
, из-за сложностей, возникающих приcd
прохождении через символические ссылки, имеет ли bash установленный-o physical
параметр и так далее. Раньше это было особенно неприятно при работе с автоматически монтируемыми каталогами, когда запись физического пути вместо логического давала бы путь, который, в случае его использования, позволял бы автомонтированию самопроизвольно отключать каталог, который он использовал.sh
и,csh
если вы хотели, чтобы клавиша Backspace работала, вам нужно было прочитать всюstty
справочную страницу, и нам понравилось!»Используйте
basename
программу. Для вашего случая:источник
basename
программы? Что не так с этим ответом, кроме пропущенных кавычек?basename
действительно внешняя программа , которая делает правильно, но работает любую внешнюю программу для вещи Баша может делать вне коробки , используя только встроенные функции глупо, подвергаясь влиянием на производительность (fork()
,execve()
,wait()
и т.д.) для нет причин.basename
здесь не применимыdirname
, потому чтоdirname
имеет функциональность,${PWD##*/}
которой нет - например, преобразование строки без косой черты.
. Таким образом, хотя использованиеdirname
в качестве внешнего инструмента приводит к снижению производительности, оно также имеет функциональность, которая помогает компенсировать его.function
ключевое слово несовместимо с POSIX, не добавляя никакого значения к стандартизированному синтаксису, а отсутствие кавычек может привести к ошибкам в именах каталогов с пробелами.wdexec() { "./$(basename "$PWD")"; }
может быть предпочтительной альтернативой.basename
менее «эффективно». Но это, вероятно, более эффективно с точки зрения производительности разработчика, потому что его легко запомнить по сравнению с уродливым синтаксисом bash. Так что, если вы помните это, пойти на это. В противном случаеbasename
работает так же хорошо. Кто-нибудь когда-нибудь должен был улучшить «производительность» bash-скрипта и сделать его более эффективным?
источник
echo "${PWD##*/}"
.name=${PWD##*/}
было бы правильно иname=$(echo "${PWD##*/}")
неправильно (в смысле ненужной неэффективности).Вы можете использовать комбинацию pwd и basename. Например
источник
Как насчет grep:
источник
pwd | xargs basename
это не так… вероятно, это не так важно, но другой ответ проще и более последовательный в разных средахМне нравится выбранный ответ (Чарльз Даффи), но будьте осторожны, если вы находитесь в директории с символическими ссылками и хотите указать имя целевой директории. К сожалению, я не думаю, что это можно сделать в выражении расширения с одним параметром, возможно, я ошибаюсь. Это должно работать:
Чтобы увидеть это, эксперимент:
сообщает "бар"
DIRNAME
Чтобы показать ведущие каталоги пути (без использования fork-exec / usr / bin / dirname):
Это, например, преобразует foo / bar / baz -> foo / bar
источник
readlink -f
это расширение GNU, и поэтому не доступно на BSD (включая OS X).Если вы используете оболочку Bourne или
${PWD##*/}
недоступны.источник
${PWD##*/}
это POSIX sh - каждый современный / bin / sh (включая dash, ash и т. Д.) Поддерживает его; чтобы поразить настоящую Борн на недавнем боксе, вам нужно будет использовать слегка устаревшую систему Solaris. Помимо этого -echo "$PWD"
; пропуск кавычек приводит к ошибкам (если в имени каталога есть пробелы, подстановочные знаки и т. д.).Эта тема отличная! Вот еще один аромат:
источник
Удивительно, но никто не упомянул об этой альтернативе, которая использует только встроенные команды bash:
В качестве дополнительного бонуса вы можете легко получить имя родительского каталога с помощью:
Они будут работать на Bash 4.3-alpha или новее.
источник
Использование:
ИЛИ
Верните внутренний разделитель имен файлов (IFS) обратно в пробел.
После IFS есть один пробел.
источник
или
источник
pwd
разделяются на строки и расширяются глобально, прежде чем будут переданыbasename
.basename "$(pwd)"
- хотя это очень неэффективно по сравнению с justbasename "$PWD"
, что само по себе неэффективно по сравнению с использованием раскрытия параметра вместо вызоваbasename
вообще.Для поиска жокеев, таких как я:
источник
$PWD
чтобы"$PWD"
правильно обрабатывать необычные имена каталогов.я обычно использую это в скриптах sh
Вы можете использовать это для автоматизации вещей ...
источник
readlink: illegal option -- f usage: readlink [-n] [file ...]
Ниже grep с регулярным выражением также работает,
источник
Просто используйте:
или
источник
xargs
Формула неэффективна и содержит ошибки, когда имена каталогов содержат буквенные символы новой строки или символы кавычек, а вторая формулировка вызываетpwd
команду в подоболочке, вместо того, чтобы получить тот же результат через встроенное расширение переменной.Если вы хотите видеть только текущий каталог в области приглашения bash, вы можете отредактировать
.bashrc
файл в~
. Изменение\w
к\W
в строке:Запустить
source ~/.bashrc
и он будет отображать только имя каталога в области подсказки.Ссылка: /superuser/60555/show-only-current-directory-name-not-full-path-on-bash-prompt
источник
Вы можете использовать утилиту basename, которая удаляет любой префикс, заканчивающийся на / и суффикс (если присутствует в строке) из строки, и выводит результат на стандартный вывод.
источник
Я настоятельно предпочитаю использовать
gbasename
, который является частью GNU coreutils.источник
basename
там. Обычноgbasename
он вызывается только на MacOS и других платформах, которые в противном случае поставляются с базовым именем не-GNU.Следующие команды приведут к печати вашего текущего рабочего каталога в bash-скрипте.
источник
$1
будет содержать текущий рабочий каталог. (2)pushd
иpopd
не служит никакой цели здесь , потому что что - то внутри обратных кавычек делаются в субоболочке - поэтому он не может повлиять на каталог родительской оболочки, чтобы начать с. (3) Использование"$(cd "$1"; pwd)"
будет более читабельным и устойчивым к именам каталогов с пробелами.