В качестве аргументов моего скрипта есть несколько путей к файлам. Они, конечно, могут быть относительными (или содержать ~). Но для функций, которые я написал, мне нужны абсолютные пути, но не разрешенные символические ссылки.
Есть ли для этого какая-нибудь функция?
linux
bash
absolute-path
лаар
источник
источник
readlink
разрешает символические ссылки; ОП этого не хочет.echo $(cd some_directory && pwd)
, не разрешать символическую ссылку, завершается ошибкой, если some_directory не существует. рабочий каталог не затронут. или присвоить переменнойMY_PATH=$(cd some_directory && pwd)
.Ответы:
MY_PATH=$(readlink -f $YOUR_ARG)
разрешит относительные пути, такие как"./"
и"../"
Учтите и это ( источник ):
#!/bin/bash dir_resolve() { cd "$1" 2>/dev/null || return $? # cd to desired directory; if fail, quell any error messages but return exit status echo "`pwd -P`" # output full, link-resolved path } # sample usage if abs_path="`dir_resolve \"$1\"`" then echo "$1 resolves to $abs_path" echo pwd: `pwd` # function forks subshell, so working directory outside function is not affected else echo "Could not reach $1" fi
источник
man pwd
: "-P Показать физический текущий рабочий каталог (все символические ссылки разрешены)", просто удалите-P
readlink -f
функциональность в OS X, вы можете использовать Homebrew, а затем запустить:$ brew install coreutils
Затем вы можете использоватьgreadlink -f
.http://www.linuxquestions.org/questions/programming-9/bash-script-return-full-path-and-filename-680368/page3.html имеет следующее
function abspath { if [[ -d "$1" ]] then pushd "$1" >/dev/null pwd popd >/dev/null elif [[ -e "$1" ]] then pushd "$(dirname "$1")" >/dev/null echo "$(pwd)/$(basename "$1")" popd >/dev/null else echo "$1" does not exist! >&2 return 127 fi }
который использует
pushd
/popd
для перехода вpwd
полезное состояние.источник
DIRSTACK
и ничего больше. Хорошее решение!sh
совместимости,pushd; cd <dir>; <cmd>; popd
его можно заменить на(cd <dir>; <cmd>)
.Простой однострочный:
function abs_path { (cd "$(dirname '$1')" &>/dev/null && printf "%s/%s" "$PWD" "${1##*/}") }
Применение:
function do_something { local file=$(abs_path $1) printf "Absolute path to %s: %s\n" "$1" "$file" } do_something $HOME/path/to/some\ where
Я все еще пытаюсь понять, как заставить его полностью забыть о том, существует ли путь или нет (чтобы его можно было использовать и при создании файлов).
источник
cd -
потом его сбросить?${1##*/}
на,basename
хотя, без помещения его в отдельную переменную, пути с пробелами не работают должным образом.$PWD
и пропустите его через него, он должен работать достаточно хорошо: github.com/andsens/homeshick/blob/…Это помогает мне в OS X:
$(cd SOME_DIRECTORY 2> /dev/null && pwd -P)
Он должен работать где угодно. Остальные решения казались слишком сложными.
источник
в OS X вы можете использовать
stat -f "%N" YOUR_PATH
в Linux у вас может быть
realpath
исполняемый файл. в противном случае может работать следующее (не только для ссылок):источник
stat -f "%N" PATH
дает мне тот же путь, что и я.Используйте
readlink -f <relative-path>
, например,export FULLPATH=`readlink -f ./`
источник
Возможно, это более читабельно и не использует подоболочку и не меняет текущий каталог:
dir_resolve() { local dir=`dirname "$1"` local file=`basename "$1"` pushd "$dir" &>/dev/null || return $? # On error, return error code echo "`pwd -P`/$file" # output full, link-resolved path with filename popd &> /dev/null }
источник
Есть другой способ. Вы можете использовать встраивание python в сценарий bash для разрешения относительного пути.
abs_path=$(python3 - <<END from pathlib import Path path = str(Path("$1").expanduser().resolve()) print(path) END )
источник
Самостоятельное редактирование, я только что заметил, что OP сказал, что не ищет разрешенных символических ссылок:
«Но для функций, которые я написал, мне нужны абсолютные пути, но не разрешенные символические ссылки».
Так что угадайте, что это не совсем так по поводу его вопроса. :)
Поскольку я сталкивался с этим много раз на протяжении многих лет, и на этот раз мне нужна была портативная версия на чистом bash, которую я мог бы использовать в OSX и Linux, я пошел дальше и написал одну:
Здесь живет живая версия:
https://github.com/keen99/shell-functions/tree/master/resolve_path
но ради ТАК, вот текущая версия (я считаю, что она хорошо протестирована ... но я открыт для отзывов!)
Может быть нетрудно заставить его работать с простой оболочкой bourne (sh), но я не пробовал ... Мне слишком нравится $ FUNCNAME. :)
#!/bin/bash resolve_path() { #I'm bash only, please! # usage: resolve_path <a file or directory> # follows symlinks and relative paths, returns a full real path # local owd="$PWD" #echo "$FUNCNAME for $1" >&2 local opath="$1" local npath="" local obase=$(basename "$opath") local odir=$(dirname "$opath") if [[ -L "$opath" ]] then #it's a link. #file or directory, we want to cd into it's dir cd $odir #then extract where the link points. npath=$(readlink "$obase") #have to -L BEFORE we -f, because -f includes -L :( if [[ -L $npath ]] then #the link points to another symlink, so go follow that. resolve_path "$npath" #and finish out early, we're done. return $? #done elif [[ -f $npath ]] #the link points to a file. then #get the dir for the new file nbase=$(basename $npath) npath=$(dirname $npath) cd "$npath" ndir=$(pwd -P) retval=0 #done elif [[ -d $npath ]] then #the link points to a directory. cd "$npath" ndir=$(pwd -P) retval=0 #done else echo "$FUNCNAME: ERROR: unknown condition inside link!!" >&2 echo "opath [[ $opath ]]" >&2 echo "npath [[ $npath ]]" >&2 return 1 fi else if ! [[ -e "$opath" ]] then echo "$FUNCNAME: $opath: No such file or directory" >&2 return 1 #and break early elif [[ -d "$opath" ]] then cd "$opath" ndir=$(pwd -P) retval=0 #done elif [[ -f "$opath" ]] then cd $odir ndir=$(pwd -P) nbase=$(basename "$opath") retval=0 #done else echo "$FUNCNAME: ERROR: unknown condition outside link!!" >&2 echo "opath [[ $opath ]]" >&2 return 1 fi fi #now assemble our output echo -n "$ndir" if [[ "x${nbase:=}" != "x" ]] then echo "/$nbase" else echo fi #now return to where we were cd "$owd" return $retval }
вот классический пример, благодаря brew:
%% ls -l `which mvn` lrwxr-xr-x 1 draistrick 502 29 Dec 17 10:50 /usr/local/bin/mvn@ -> ../Cellar/maven/3.2.3/bin/mvn
используйте эту функцию, и она вернет -real- путь:
%% cat test.sh #!/bin/bash . resolve_path.inc echo echo "relative symlinked path:" which mvn echo echo "and the real path:" resolve_path `which mvn` %% test.sh relative symlinked path: /usr/local/bin/mvn and the real path: /usr/local/Cellar/maven/3.2.3/libexec/bin/mvn
источник
Если ваша ОС поддерживает это, используйте:
realpath "./some/dir"
И используя его в переменной:
some_path="$(realpath "./some/dir")"
Что расширит ваш путь. Протестировано на Ubuntu и CentOS, может быть недоступно на вашем. Некоторые рекомендуют readlink, но документация для readlink говорит:
Если люди задаются вопросом, почему я цитирую свои переменные, это для сохранения пробелов в путях. Подобное действие
realpath some path
даст вам два разных пути. Ноrealpath "some path"
вернется один. Цитируемые параметры ftw :)источник
Вам нужно использовать исключительно bash? Мне нужно было это сделать, и мне надоели различия между Linux и OS X. Поэтому я использовал PHP для быстрого и грязного решения.
#!/usr/bin/php <-- or wherever <?php { if($argc!=2) exit(); $fname=$argv[1]; if(!file_exists($fname)) exit(); echo realpath($fname)."\n"; } ?>
Я знаю, что это не очень элегантное решение, но оно работает.
источник