realpathкажется, не доступно на Mac (OS X 10.11 "El Capitan"). :-(
Ларикс Децидуа
realpathПохоже, что он недоступен в CentOS 6
user5359531
6
на OSX, brew install coreutilsпринесетrealpath
Кевин Чен
На моем Ubuntu 18.04, realpathуже присутствует. Мне не нужно было устанавливать его отдельно.
Acumenus
Удивительно, но realpathдоступен на Git для Windows (для меня, по крайней мере).
Эндрю Китон
104
Если у вас установлен пакет coreutils, вы можете использовать его readlink -f relative_file_nameдля получения абсолютного пакета (со всеми разрешенными символическими ссылками).
Поведение для этого немного отличается от того, что запрашивает пользователь, оно также будет следовать и разрешать рекурсивные символические ссылки в любом месте пути. Вы можете не хотеть этого в некоторых случаях.
окопался
1
@BradPeabody Это работает на Mac, если вы устанавливаете coreutils из homebrew brew install coreutils. Однако к исполняемому файлу добавляется ag:greadlink -f relative_file_name
Мигель Исла
2
Обратите внимание, что страница руководства readlink (1) имеет в качестве первого предложения своего описания: «Обратите внимание, что realpath (1) является предпочтительной командой для использования для функций канонизации».
Йош
1
вы можете использовать -e вместо -f, чтобы проверить, существует ли файл / каталог или нет
readlink - это простое решение для linux, но это решение работает и на OSX, поэтому +1
thetoolman
1
Этот сценарий не эквивалентен тому, что realpathили readlink -fделать. Например, он не работает с путями, где последний компонент является символической ссылкой.
Йош
2
@josch: Вопрос не в разрешении символических ссылок. Но если вы хотите сделать это, вы можете предоставить -Pопцию pwdкоманды:echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Евгений Коньков
4
Мне нравится ответ, но он работает только в том случае, если пользователю разрешено перейти в каталог. Это не всегда возможно.
Матиас Б
34
За то, что это стоит, я проголосовал за ответ, который был выбран, но хотел поделиться решением. Недостатком является то, что это только Linux - я потратил около 5 минут, пытаясь найти эквивалент OSX, прежде чем перейти к переполнению стека. Я уверен, что это там, хотя
На Linux вы можете использовать readlink -eв тандеме с dirname.
$(dirname $(readlink -e ../../../../etc/passwd))
доходность
/etc/
А потом вы используете dirnameсестру, basenameчтобы просто получить имя файла
Отличная запись с dirname, readlinkи basename. Это помогло мне получить абсолютный путь символической ссылки, а не ее цель.
Кевинарпе
Не работает, когда вы хотите вернуть путь к символическим ссылкам (что мне просто нужно сделать ...).
Томаш Зато - Восстановить Монику
Как вы можете найти абсолютный путь к пути, который не существует?
синтезаторпатель
@synthesizerpatel Довольно легко, я бы подумал; если я вхожу /home/GKFXи touch newfileпечатаю, то перед нажатием клавиши ввода вы можете решить, что я имею в виду «create / home / GKFX / newfile», то есть абсолютный путь к файлу, который еще не существует.
GKFX
25
Я думаю, что это самый портативный:
abspath(){
cd "$(dirname "$1")"
printf "%s/%s\n""$(pwd)""$(basename "$1")"
cd "$OLDPWD"}
Там нет необходимости снова CD. См. Stackoverflow.com/a/21188136/1504556 . Ваш лучший ответ на этой странице, ИМХО. Для интересующихся ссылка дает объяснение, почему это решение работает.
Петер
Это не очень переносимая dirnameутилита ядра GNU, которая, на мой взгляд, не является общей для всех Unixen.
Боже мой, спасибо. Я пытался исправить версию, которая используется ${1##*/}в течение дня, и теперь, когда я заменил этот мусор, basename "$1"он, кажется, наконец-то правильно обрабатывает пути, заканчивающиеся на /.
l3l_aze
NB, это не делает правильную вещь с путем, заканчивающимся в../..
Алекс Ковентри
16
realpath наверное лучше
Но ...
Начальный вопрос был очень запутанным, с примера, плохо связанного с вопросом, как указано.
Выбранный ответ на самом деле отвечает приведенному примеру, а не на вопрос в заголовке. Первая команда - это ответ (действительно ли это? Я сомневаюсь), и она может обойтись без '/'. И я не вижу, что делает вторая команда.
Несколько вопросов смешаны:
изменение относительного пути в абсолютное, что бы оно ни обозначало, возможно, ничего. ( Как правило, если вы запускаете команду, такую как touch foo/bar, имя пути foo/barдолжно существовать для вас и, возможно, использоваться в вычислениях, прежде чем файл будет фактически создан. )
может быть несколько абсолютных путей, обозначающих один и тот же файл (или потенциальный файл), особенно из-за символических ссылок (символических ссылок) на пути, но, возможно, по другим причинам (устройство может быть смонтировано дважды только для чтения). Можно или не может хотеть разрешить эксплицитность таких символических ссылок.
добраться до конца цепочки символических ссылок на несимвольный файл или имя. Это может или не может привести к абсолютному пути, в зависимости от того, как это делается. И кто-то может или не может хотеть разрешить его в абсолютном пути.
Команда readlink fooбез опции дает ответ, только если ее аргумент fooявляется символической ссылкой, и этот ответ является значением этой символической ссылки. Никакой другой ссылки не последовало. Ответ может быть относительным путем: каким бы ни было значение аргумента символической ссылки.
Тем readlinkне менее, имеет параметры (-f -e или -m), которые будут работать для всех файлов и давать одно абсолютное имя пути (без символьных ссылок) для файла, фактически обозначенного аргументом.
Это прекрасно работает для всего, что не является символической ссылкой, хотя можно использовать абсолютный путь без разрешения промежуточных символических ссылок в пути. Это делается командойrealpath -s foo
В случае аргумента символической ссылки readlinkего параметры снова разрешат все символические ссылки на абсолютном пути к аргументу, но это также будет включать в себя все символические ссылки, которые могут встретиться после значения аргумента. Возможно, вы не захотите этого, если вам нужен абсолютный путь к самой символической ссылке на аргумент, а не к тому, на что он может ссылаться. Опять же, если fooэто символьная ссылка, realpath -s fooполучит абсолютный путь без разрешения символических ссылок, включая указанную в качестве аргумента.
Без -sопции realpathделает то же самое
readlink, за исключением простого чтения значения ссылки, а также некоторых других вещей. Мне просто не понятно, почему readlinkесть свои варианты, создающие, по-видимому, нежелательную избыточность с помощью
realpath.
Изучение Интернета не говорит о многом, за исключением того, что могут быть некоторые различия между системами.
Вывод: realpathэто лучшая команда для использования с максимальной гибкостью, по крайней мере, для использования, запрошенного здесь.
Мое любимое решение было один на @EugenKonkov , потому что это не означает наличие других коммунальных услуг (пакет Coreutils).
Но это не удалось для относительных путей "." и "..", так что здесь есть немного улучшенная версия для обработки этих особых случаев.
Однако он по-прежнему не работает, если у пользователя нет прав доступа к cdродительскому каталогу с относительным путем.
#! /bin/sh# Takes a path argument and returns it as an absolute path. # No-op if the path is already absolute.function to-abs-path {local target="$1"if["$target"=="."];then
echo "$(pwd)"elif["$target"==".."];then
echo "$(dirname "$(pwd)")"else
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"fi}
Если вы используете Баш на Mac OS X , который ни один не Realpath существовал ни его readlink может напечатать абсолютный путь, вы можете иметь выбор , кроме кода своей собственной версии , чтобы распечатать его. Вот моя реализация:
(чистый удар)
abspath(){local thePath
if[[!"$1"=~^/]];then
thePath="$PWD/$1"else
thePath="$1"fi
echo "$thePath"|(
IFS=/
read -a parr
declare -a outp
for i in"${parr[@]}";docase"$i"in''|.)continue;;..)
len=${#outp[@]}if((len==0));thencontinueelse
unset outp[$((len-1))]fi;;*)
len=${#outp[@]}
outp[$len]="$i";;esacdone
echo /"${outp[*]}")}
(используйте gawk)
abspath_gawk(){if[[-n "$1"]];then
echo $1|gawk '{
if(substr($0,1,1) != "/"){
path = ENVIRON["PWD"]"/"$0
} else path = $0
split(path, a, "/")
n = asorti(a, b,"@ind_num_asc")
for(i in a){
if(a[i]=="" || a[i]=="."){
delete a[i]
}
}
n = asorti(a, b, "@ind_num_asc")
m = 0
while(m!=n){
m = n
for(i=1;i<=n;i++){
if(a[b[i]]==".."){
if(b[i-1] in a){
delete a[b[i-1]]
delete a[b[i]]
n = asorti(a, b, "@ind_num_asc")
break
} else exit 1
}
}
}
n = asorti(a, b, "@ind_num_asc")
if(n==0){
printf "/"
} else {
for(i=1;i<=n;i++){
printf "/"a[b[i]]
}
}
}'fi}
Спасибо за этот фрагмент кода, который может предоставить некоторую ограниченную краткосрочную помощь. Правильное объяснение значительно улучшило бы его долгосрочную ценность, показав, почему это хорошее решение проблемы, и сделало бы его более полезным для будущих читателей с другими, похожими вопросами. Пожалуйста, измените свой ответ, чтобы добавить некоторые объяснения, в том числе предположения, которые вы сделали.
Это правильно относится к случаю, когда последним элементом пути является .., и в этом случае "$(pwd)/$(basename "$1")"ответ in @ ernest-a будет выглядеть как accurate_sub_path/spurious_subdirectory/...
На bash-4.3-p46 это не работает: оболочка печатает пустую строку, когда я запускаюdir=`cd ".."` && echo $dir
Michael
0
Это связанное решение от всех остальных, например, когда происходит realpathсбой, либо потому, что оно не установлено, либо потому, что оно завершается с кодом ошибки, затем предпринимается попытка следующего решения, пока он не получит правильный путь.
Мне не удалось найти решение, которое было бы легко переносимым между Mac OS Catalina, Ubuntu 16 и Centos 7, поэтому я решил сделать это с помощью встроенного Python, и оно хорошо работало для моих скриптов bash.
Ответы:
использовать:
чтобы получить все файлы или
отображать полный путь (если относительный путь имеет значение для)
источник
$(pwd)
вместо$PWD
? (да, я знаюpwd
, это встроенный)Попробуй
realpath
.Чтобы избежать расширения символических ссылок, используйте
realpath -s
.Ответ приходит от команды bash / fish для вывода абсолютного пути к файлу .
источник
realpath
кажется, не доступно на Mac (OS X 10.11 "El Capitan"). :-(realpath
Похоже, что он недоступен в CentOS 6brew install coreutils
принесетrealpath
realpath
уже присутствует. Мне не нужно было устанавливать его отдельно.realpath
доступен на Git для Windows (для меня, по крайней мере).Если у вас установлен пакет coreutils, вы можете использовать его
readlink -f relative_file_name
для получения абсолютного пакета (со всеми разрешенными символическими ссылками).источник
brew install coreutils
. Однако к исполняемому файлу добавляется ag:greadlink -f relative_file_name
UPD Некоторые объяснения
"$1"
dirname "$1"
cd "$(dirname "$1")
в этот относительный каталог и получаем абсолютный путь к нему, выполнивpwd
команду shell$(basename "$1")
echo
этоисточник
realpath
илиreadlink -f
делать. Например, он не работает с путями, где последний компонент является символической ссылкой.-P
опциюpwd
команды:echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
За то, что это стоит, я проголосовал за ответ, который был выбран, но хотел поделиться решением. Недостатком является то, что это только Linux - я потратил около 5 минут, пытаясь найти эквивалент OSX, прежде чем перейти к переполнению стека. Я уверен, что это там, хотя
На Linux вы можете использовать
readlink -e
в тандеме сdirname
.доходность
А потом вы используете
dirname
сестру,basename
чтобы просто получить имя файладоходность
Поставить все это вместе..
доходность
Вы в безопасности, если вы нацеливаетесь на каталог,
basename
ничего не вернете, и в конечном итоге вы получите двойную косую черту.источник
dirname
,readlink
иbasename
. Это помогло мне получить абсолютный путь символической ссылки, а не ее цель./home/GKFX
иtouch newfile
печатаю, то перед нажатием клавиши ввода вы можете решить, что я имею в виду «create / home / GKFX / newfile», то есть абсолютный путь к файлу, который еще не существует.Я думаю, что это самый портативный:
Это не удастся, если путь не существует, хотя.
источник
dirname
утилита ядра GNU, которая, на мой взгляд, не является общей для всех Unixen.dirname
- стандартная утилита POSIX, см. здесь: pubs.opengroup.org/onlinepubs/9699919799/utilities/dirname.html${1##*/}
в течение дня, и теперь, когда я заменил этот мусор,basename "$1"
он, кажется, наконец-то правильно обрабатывает пути, заканчивающиеся на /.../..
realpath
наверное лучшеНо ...
Начальный вопрос был очень запутанным, с примера, плохо связанного с вопросом, как указано.
Выбранный ответ на самом деле отвечает приведенному примеру, а не на вопрос в заголовке. Первая команда - это ответ (действительно ли это? Я сомневаюсь), и она может обойтись без '/'. И я не вижу, что делает вторая команда.
Несколько вопросов смешаны:
изменение относительного пути в абсолютное, что бы оно ни обозначало, возможно, ничего. ( Как правило, если вы запускаете команду, такую как
touch foo/bar
, имя путиfoo/bar
должно существовать для вас и, возможно, использоваться в вычислениях, прежде чем файл будет фактически создан. )может быть несколько абсолютных путей, обозначающих один и тот же файл (или потенциальный файл), особенно из-за символических ссылок (символических ссылок) на пути, но, возможно, по другим причинам (устройство может быть смонтировано дважды только для чтения). Можно или не может хотеть разрешить эксплицитность таких символических ссылок.
добраться до конца цепочки символических ссылок на несимвольный файл или имя. Это может или не может привести к абсолютному пути, в зависимости от того, как это делается. И кто-то может или не может хотеть разрешить его в абсолютном пути.
Команда
readlink foo
без опции дает ответ, только если ее аргументfoo
является символической ссылкой, и этот ответ является значением этой символической ссылки. Никакой другой ссылки не последовало. Ответ может быть относительным путем: каким бы ни было значение аргумента символической ссылки.Тем
readlink
не менее, имеет параметры (-f -e или -m), которые будут работать для всех файлов и давать одно абсолютное имя пути (без символьных ссылок) для файла, фактически обозначенного аргументом.Это прекрасно работает для всего, что не является символической ссылкой, хотя можно использовать абсолютный путь без разрешения промежуточных символических ссылок в пути. Это делается командой
realpath -s foo
В случае аргумента символической ссылки
readlink
его параметры снова разрешат все символические ссылки на абсолютном пути к аргументу, но это также будет включать в себя все символические ссылки, которые могут встретиться после значения аргумента. Возможно, вы не захотите этого, если вам нужен абсолютный путь к самой символической ссылке на аргумент, а не к тому, на что он может ссылаться. Опять же, еслиfoo
это символьная ссылка,realpath -s foo
получит абсолютный путь без разрешения символических ссылок, включая указанную в качестве аргумента.Без
-s
опцииrealpath
делает то же самоеreadlink
, за исключением простого чтения значения ссылки, а также некоторых других вещей. Мне просто не понятно, почемуreadlink
есть свои варианты, создающие, по-видимому, нежелательную избыточность с помощьюrealpath
.Изучение Интернета не говорит о многом, за исключением того, что могут быть некоторые различия между системами.
Вывод:
realpath
это лучшая команда для использования с максимальной гибкостью, по крайней мере, для использования, запрошенного здесь.источник
Мое любимое решение было один на @EugenKonkov , потому что это не означает наличие других коммунальных услуг (пакет Coreutils).
Но это не удалось для относительных путей "." и "..", так что здесь есть немного улучшенная версия для обработки этих особых случаев.
Однако он по-прежнему не работает, если у пользователя нет прав доступа к
cd
родительскому каталогу с относительным путем.источник
Ответ Евгения не совсем сработал для меня, но это сработало:
Примечание: ваш текущий рабочий каталог не затронут.
источник
Наилучшим решением, imho, является то, которое размещено здесь: https://stackoverflow.com/a/3373298/9724628 .
Для работы требуется python, но, похоже, он охватывает все или большинство крайних случаев и является очень портативным решением.
источник
В случае
find
, вероятно, проще всего просто указать абсолютный путь для поиска, например:источник
Если вы используете Баш на Mac OS X , который ни один не Realpath существовал ни его readlink может напечатать абсолютный путь, вы можете иметь выбор , кроме кода своей собственной версии , чтобы распечатать его. Вот моя реализация:
(чистый удар)
(используйте gawk)
(чистый BSD AWK)
пример:
источник
То, что они сказали, кроме
find $PWD
или (в bash)find ~+
немного удобнее.источник
Подобно ответу @ ernest-a, но без влияния
$OLDPWD
на новую функцию или определения ее, вы можете запустить подоболочку(cd <path>; pwd)
источник
Если относительный путь является путем к каталогу, попробуйте мой, должно быть лучше:
источник
источник
Улучшение довольно приятной версии @ ernest-a:
Это правильно относится к случаю, когда последним элементом пути является
..
, и в этом случае"$(pwd)/$(basename "$1")"
ответ in @ ernest-a будет выглядеть какaccurate_sub_path/spurious_subdirectory/..
.источник
Если вы хотите преобразовать переменную, содержащую относительный путь, в абсолютный, это работает:
«CD» эхом без изменения рабочего каталога, потому что выполняется здесь в под-оболочке.
источник
dir=`cd ".."` && echo $dir
Это связанное решение от всех остальных, например, когда происходит
realpath
сбой, либо потому, что оно не установлено, либо потому, что оно завершается с кодом ошибки, затем предпринимается попытка следующего решения, пока он не получит правильный путь.источник
Вы можете использовать подстановку строки bash для любого относительного пути $ line:
Основная подстановка перед строкой следует формуле
$ {string / # substring / replace},
которая хорошо обсуждается здесь: https://www.tldp.org/LDP/abs/html/string-manipulation.html.
Символ
\
отрицает,/
когда мы хотим, чтобы он был частью строки, которую мы находим / заменяем.источник
Мне не удалось найти решение, которое было бы легко переносимым между Mac OS Catalina, Ubuntu 16 и Centos 7, поэтому я решил сделать это с помощью встроенного Python, и оно хорошо работало для моих скриптов bash.
источник