Просто попробуйте использовать приложение "xkill". Он предназначен именно для таких казусов.
Bash поставляется с realpath
загружаемым расширением. Начиная с bash -4.4, он должен быть установлен по умолчанию¹, поэтому вы сможете сделать:
BASH_LOADABLES_PATH=${BASH_LOADABLES_PATH:-/usr/local/lib/bash:/usr/lib/bash}
enable -f realpath realpath
realpath..
help realpath
После включения каждая загружаемая команда становится «настоящей» встроенной без дополнительных затрат на fork/exec и с возможностью манипулировать средой bash (, где это предлагается, например. mypid
загружаемый )...
Параметр -f
указывает путь к загружаемому бинарному файлу расширения, если его нет в ожидаемом месте или ваш дистрибутив не установил его правильно, вам нужно будет установить переменную BASH_LOADABLES_PATH
в каталог, содержащий расширения (или используйте -f
с полным путем к загружаемому файлу ). Если он установлен правильно, вам не понадобится первая строка выше.
При написании переносимых скриптов, которые предпочитают, но не требуют таких расширений, я все равно буду использовать функцию-оболочку — по аналогии с @Kusalananda — чтобы она могла вернуться к внешнему (, такому как readlink
или realpath
из coreutils).
Некоторые системы имеют команду «realpath», например. Убунту. Вы можете попробовать realpath ~/foo.txt
, и это может дать что-то вроде /home/user/foo.txt
, затем вы можете использовать basedir
, чтобы обрезать имя файла.
Оболочка bash
не имеет встроенного -способа явного получения абсолютного пути по относительному имени пути.
В оболочке zsh
можно было сделать
pathname=../../home/kk/.zshenv
print -r -- $pathname:P
и получить /home/kk/.zshenv
обратно (обратите внимание, что он также разрешает все символические ссылки везде, где это возможно, аналогично тому, как realpath()
будет ).
В bash
вы могли бы, для имени пути, обозначающего каталог, отличный от -, и предполагая, что у вас есть доступ к его родительскому каталогу, использовать
$ pathname=../../home/kk/.zshenv
$ ( OLDPWD=- CDPATH= cd -P -- "${pathname%/*}" && printf '%s/%s\n' "$PWD" "${pathname##*/}" )
/home/kk/.zshenv
То есть временно (в под-оболочке)cd
в каталог, содержащий файл, а затем создать абсолютный путь, используя значение $PWD
и компонент имени файла пути. -P
необходим, чтобы избежать специальной обработки cd
компонентов ..
. Это имеет побочный эффект разрешения компонентов символических ссылок в самом каталоге. Однако, если сам файл является символической ссылкой, он не будет разрешен (в этом отличие от zsh
модификатора :P
).
Мы установили OLDPWD
в -
, чтобы обойти тот факт, что cd -P -- -
выполняет chdir($OLDPWD)
вместо chdir("-")
(, этот трюк работает в bash
, но не во всех других sh
реализациях ).
Для пути к каталогу проще:
$ pathname=../../home/kk
$ ( OLDPWD=- CDPATH= cd -P -- "$pathname" && pwd )
/home/kk
Это, очевидно, можно было бы поместить в функцию оболочки для удобства:
myrealpath () (
if [[ -d $1 ]]; then
OLDPWD=- CDPATH= cd -P -- "$1" && pwd
else
OLDPWD=- CDPATH= cd -P -- "${1%/*}" && printf '%s/%s\n' "$PWD" "${1##*/}"
fi
)
(Обратите внимание, что вся эта функция определена в оболочке sub -, чтобы избежать изменения рабочего каталога для вызывающей оболочки.)
Проверка этой функции:
$ myrealpath../../home/kk
/home/kk
$ myrealpath../../home/kk/.zshenv
/home/kk/.zshenv
В зависимости от ОС использование функции без аргументов вернет абсолютный путь к текущему каталогу или выдаст ошибку. В будущих версиях bash
это, вероятно, будет ошибкой на каждой системе, так как отказ cd ''
станет требованием POSIX.
Я предлагаю следующее, которое с высокой вероятностью будет работать в ОС, отличных от -Linux (, включая AIX ). Чтобы вычислить абсолютный путь (, то есть путь, начинающийся с/
):
abspath() {
[[ $1 = /* ]] && printf "%s\n" "$1" || printf "%s\n" "$PWD/$1"
}
Для канонического пути (, т. е. пути со всеми развернутыми символическими ссылками):
canonical_path() {
perl -mCwd -le ' print Cwd::abs_path $ARGV[0] ' -- "$1"
}
При тестировании с другими возможными решениями (, включая вызов realpath
), вы заметите значительную разницу в зависимости от того, существует ли последний компонент пути и является ли последний компонент пути символической ссылкой.