Как бы получить текущее имя рабочего каталога в скрипте bash или, что еще лучше, просто команду терминала.
pwd
дает полный путь текущего рабочего каталога, например, /opt/local/bin
но я хочу толькоbin
Как бы получить текущее имя рабочего каталога в скрипте bash или, что еще лучше, просто команду терминала.
pwd
дает полный путь текущего рабочего каталога, например, /opt/local/bin
но я хочу толькоbin
Ответы:
Нет необходимости в базовом имени, и особенно нет необходимости в подоболочке, выполняющей pwd (которая добавляет дополнительную и дорогую операцию fork ); оболочка может сделать это внутренне, используя расширение параметров :
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 /
$PWD
- это имя встроенной переменной bash; все встроенные имена переменных указаны заглавными буквами (чтобы отличать их от локальных переменных, которые всегда должны иметь хотя бы один символ нижнего регистра). result=${PWD#*/}
делает не вычисляться /full/path/to/directory
; вместо этого он удаляет только первый элемент, делая его path/to/directory
; использование двух #
символов делает сопоставление шаблона жадным, сопоставляя столько символов, сколько возможно. Прочитайте страницу расширения параметров, связанную в ответе, для получения дополнительной информации.
pwd
не всегда совпадают со значением $PWD
, из-за сложностей, возникающих при cd
прохождении через символические ссылки, имеет ли bash установленный -o physical
параметр и так далее. Раньше это было особенно неприятно при работе с автоматически монтируемыми каталогами, когда запись физического пути вместо логического давала бы путь, который, в случае его использования, позволял бы автомонтированию самопроизвольно отключать каталог, который он использовал.
sh
и, csh
если вы хотели, чтобы клавиша Backspace работала, вам нужно было прочитать всю stty
справочную страницу, и нам понравилось!»
Используйте basename
программу. Для вашего случая:
% basename "$PWD"
bin
basename
программы? Что не так с этим ответом, кроме пропущенных кавычек?
basename
действительно внешняя программа , которая делает правильно, но работает любую внешнюю программу для вещи Баша может делать вне коробки , используя только встроенные функции глупо, подвергаясь влиянием на производительность ( fork()
, execve()
, wait()
и т.д.) для нет причин.
basename
здесь не применимы dirname
, потому что dirname
имеет функциональность, ${PWD##*/}
которой нет - например, преобразование строки без косой черты .
. Таким образом, хотя использование dirname
в качестве внешнего инструмента приводит к снижению производительности, оно также имеет функциональность, которая помогает компенсировать его.
function
ключевое слово несовместимо с POSIX, не добавляя никакого значения к стандартизированному синтаксису, а отсутствие кавычек может привести к ошибкам в именах каталогов с пробелами. wdexec() { "./$(basename "$PWD")"; }
может быть предпочтительной альтернативой.
basename
менее «эффективно». Но это, вероятно, более эффективно с точки зрения производительности разработчика, потому что его легко запомнить по сравнению с уродливым синтаксисом bash. Так что, если вы помните это, пойти на это. В противном случае basename
работает так же хорошо. Кто-нибудь когда-нибудь должен был улучшить «производительность» bash-скрипта и сделать его более эффективным?
$ echo "${PWD##*/}"
echo "${PWD##*/}"
.
name=${PWD##*/}
было бы правильно и name=$(echo "${PWD##*/}")
неправильно (в смысле ненужной неэффективности).
Вы можете использовать комбинацию pwd и basename. Например
#!/bin/bash
CURRENT=`pwd`
BASENAME=`basename "$CURRENT"`
echo "$BASENAME"
exit;
Мне нравится выбранный ответ (Чарльз Даффи), но будьте осторожны, если вы находитесь в директории с символическими ссылками и хотите указать имя целевой директории. К сожалению, я не думаю, что это можно сделать в выражении расширения с одним параметром, возможно, я ошибаюсь. Это должно работать:
target_PWD=$(readlink -f .)
echo ${target_PWD##*/}
Чтобы увидеть это, эксперимент:
cd foo
ln -s . bar
echo ${PWD##*/}
сообщает "бар"
Чтобы показать ведущие каталоги пути (без использования fork-exec / usr / bin / dirname):
echo ${target_PWD%/*}
Это, например, преобразует foo / bar / baz -> foo / bar
readlink -f
это расширение GNU, и поэтому не доступно на BSD (включая OS X).
echo "$PWD" | sed 's!.*/!!'
Если вы используете оболочку Bourne или ${PWD##*/}
недоступны.
${PWD##*/}
это POSIX sh - каждый современный / bin / sh (включая dash, ash и т. Д.) Поддерживает его; чтобы поразить настоящую Борн на недавнем боксе, вам нужно будет использовать слегка устаревшую систему Solaris. Помимо этого - echo "$PWD"
; пропуск кавычек приводит к ошибкам (если в имени каталога есть пробелы, подстановочные знаки и т. д.).
Удивительно, но никто не упомянул об этой альтернативе, которая использует только встроенные команды bash:
i="$IFS";IFS='/';set -f;p=($PWD);set +f;IFS="$i";echo "${p[-1]}"
В качестве дополнительного бонуса вы можете легко получить имя родительского каталога с помощью:
[ "${#p[@]}" -gt 1 ] && echo "${p[-2]}"
Они будут работать на Bash 4.3-alpha или новее.
basename $(pwd)
или
echo "$(basename $(pwd))"
pwd
разделяются на строки и расширяются глобально, прежде чем будут переданы basename
.
basename "$(pwd)"
- хотя это очень неэффективно по сравнению с just basename "$PWD"
, что само по себе неэффективно по сравнению с использованием раскрытия параметра вместо вызова basename
вообще.
Для поиска жокеев, таких как я:
find $PWD -maxdepth 0 -printf "%f\n"
$PWD
чтобы "$PWD"
правильно обрабатывать необычные имена каталогов.
я обычно использую это в скриптах sh
SCRIPTSRC=`readlink -f "$0" || echo "$0"`
RUN_PATH=`dirname "${SCRIPTSRC}" || echo .`
echo "Running from ${RUN_PATH}"
...
cd ${RUN_PATH}/subfolder
Вы можете использовать это для автоматизации вещей ...
Ниже grep с регулярным выражением также работает,
>pwd | grep -o "\w*-*$"
Просто используйте:
pwd | xargs basename
или
basename "`pwd`"
xargs
Формула неэффективна и содержит ошибки, когда имена каталогов содержат буквенные символы новой строки или символы кавычек, а вторая формулировка вызывает pwd
команду в подоболочке, вместо того, чтобы получить тот же результат через встроенное расширение переменной.
Если вы хотите видеть только текущий каталог в области приглашения bash, вы можете отредактировать .bashrc
файл в ~
. Изменение \w
к \W
в строке:
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
Запустить source ~/.bashrc
и он будет отображать только имя каталога в области подсказки.
Ссылка: /superuser/60555/show-only-current-directory-name-not-full-path-on-bash-prompt
Я настоятельно предпочитаю использовать gbasename
, который является частью GNU coreutils.
basename
там. Обычно gbasename
он вызывается только на MacOS и других платформах, которые в противном случае поставляются с базовым именем не-GNU.
Следующие команды приведут к печати вашего текущего рабочего каталога в bash-скрипте.
pushd .
CURRENT_DIR="`cd $1; pwd`"
popd
echo $CURRENT_DIR
$1
будет содержать текущий рабочий каталог. (2) pushd
и popd
не служит никакой цели здесь , потому что что - то внутри обратных кавычек делаются в субоболочке - поэтому он не может повлиять на каталог родительской оболочки, чтобы начать с. (3) Использование "$(cd "$1"; pwd)"
будет более читабельным и устойчивым к именам каталогов с пробелами.