Jako argumenty do mojego skryptu są ścieżki do plików. Mogą one oczywiście być względne (lub zawierać ~). Ale dla funkcji, które napisałem, potrzebuję ścieżek, które są bezwzględne, ale nie mają rozwiązanych ich dowiązań symbolicznych.
Czy jest do tego jakaś funkcja?
linux
bash
absolute-path
laar
źródło
źródło
readlink
rozwiązuje dowiązania symboliczne; OP tego nie chce.echo $(cd some_directory && pwd)
, nie rozwiązuj dowiązania symbolicznego, nie powiedzie się, jeśli jakiś_katalog nie istnieje. katalog roboczy nie ma wpływu. lub przypisz do zmiennejMY_PATH=$(cd some_directory && pwd)
.Odpowiedzi:
MY_PATH=$(readlink -f $YOUR_ARG)
rozwiąże ścieżki względne, takie jak"./"
i"../"
Rozważ to również ( źródło ):
#!/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
źródło
man pwd
: "-P Wyświetl fizyczny bieżący katalog roboczy (wszystkie dowiązania symboliczne rozwiązane)", po prostu usuń-P
readlink -f
funkcjonalność w systemie OS X, możesz użyć Homebrew, a następnie uruchomić:$ brew install coreutils
Możesz następnie użyćgreadlink -f
.http://www.linuxquestions.org/questions/programming-9/bash-script-return-full-path-and-filename-680368/page3.html zawiera następujące elementy
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 }
który używa
pushd
/,popd
aby wejść w stan, w którympwd
jest przydatny.źródło
DIRSTACK
i nic więcej. Niezłe rozwiązanie!sh
kompatybilności,pushd; cd <dir>; <cmd>; popd
można go zastąpić(cd <dir>; <cmd>)
.Prosta jedna linijka:
function abs_path { (cd "$(dirname '$1')" &>/dev/null && printf "%s/%s" "$PWD" "${1##*/}") }
Stosowanie:
function do_something { local file=$(abs_path $1) printf "Absolute path to %s: %s\n" "$1" "$file" } do_something $HOME/path/to/some\ where
Nadal próbuję dowiedzieć się, jak mogę to zrobić, aby całkowicie nie zdawać sobie sprawy z tego, czy ścieżka istnieje, czy nie (więc można jej używać również podczas tworzenia plików).
źródło
cd -
później go zresetować?${1##*/}
zebasename
chociaż, bez narażania go w osobnej zmiennej, ścieżki ze spacjami nie działa prawidłowo.$PWD
i przeprowadzisz ją przez nią, powinna działać całkiem dobrze: github.com/andsens/homeshick/blob/ ...To załatwia sprawę na OS X:
$(cd SOME_DIRECTORY 2> /dev/null && pwd -P)
Powinien działać wszędzie. Inne rozwiązania wydawały się zbyt skomplikowane.
źródło
na OS X, którego możesz użyć
stat -f "%N" YOUR_PATH
na Linuksie możesz mieć
realpath
plik wykonywalny. jeśli nie, poniższe mogą działać (nie tylko w przypadku linków):źródło
stat -f "%N" PATH
daje mi dokładnie tę samą ścieżkę, którą mu podałem.Użyj
readlink -f <relative-path>
npexport FULLPATH=`readlink -f ./`
źródło
Może jest to bardziej czytelne i nie używa podpowłoki i nie zmienia bieżącego katalogu:
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 }
źródło
Jest inna metoda. Możesz użyć osadzania Pythona w skrypcie bash, aby rozwiązać ścieżkę względną.
abs_path=$(python3 - <<END from pathlib import Path path = str(Path("$1").expanduser().resolve()) print(path) END )
źródło
samodzielna edycja, właśnie zauważyłem, że OP powiedział, że nie szuka rozwiązanych linków symbolicznych:
„Ale dla funkcji, które napisałem, potrzebuję ścieżek, które są bezwzględne, ale nie mają rozwiązanych dowiązań symbolicznych”.
Więc myślę, że to jednak nie jest tak odpowiednie do jego pytania. :)
Ponieważ przez lata napotykałem na to wiele razy, a tym razem potrzebowałem czystej przenośnej wersji bash, której mógłbym używać na OSX i Linuksie, napisałem jedną:
Żywa wersja mieszka tutaj:
https://github.com/keen99/shell-functions/tree/master/resolve_path
ale ze względu na SO, oto aktualna wersja (wydaje mi się, że jest dobrze przetestowana, ale jestem otwarty na opinie!)
Może nie być trudne, aby działał na zwykłej skorupie burne (sh), ale nie próbowałem ... Za bardzo lubię $ 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 }
oto klasyczny przykład, dzięki naparowi:
%% 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
użyj tej funkcji, a zwróci ona -real- ścieżkę:
%% 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
źródło
Jeśli Twój system operacyjny to obsługuje, użyj:
realpath "./some/dir"
I używając go w zmiennej:
some_path="$(realpath "./some/dir")"
Który poszerzy twoją ścieżkę. Testowany na Ubuntu i CentOS, może nie być dostępny na twoim. Niektórzy zalecają readlink, ale dokumentacja dla readlink mówi:
Na wypadek, gdyby ludzie zastanawiali się, dlaczego cytuję moje zmienne, chodzi o zachowanie spacji na ścieżkach. Jak robi
realpath some path
daje dwa różne wyniki ścieżce. Alerealpath "some path"
zwróci jeden. Podane parametry ftw :)źródło
Czy musisz używać wyłącznie basha? Musiałem to zrobić i miałem dość różnic między Linuksem i OS X. Więc użyłem PHP jako szybkiego i brudnego rozwiązania.
#!/usr/bin/php <-- or wherever <?php { if($argc!=2) exit(); $fname=$argv[1]; if(!file_exists($fname)) exit(); echo realpath($fname)."\n"; } ?>
Wiem, że to niezbyt eleganckie rozwiązanie, ale działa.
źródło