Jak uzyskać pełną ścieżkę pliku w bash?

23

Chciałbym w łatwy sposób uzyskać pełną ścieżkę do pliku. Obecnie piszę to:

echo `pwd`/file.ext

Próbując go skrócić, stworzyłem alias bash:

alias fp='echo `pwd`/'

Ale teraz, gdy piszę fp file.ext, między /i a pojawia się spacja file.ext.

Czy takie polecenie już istnieje i brakuje mi go? Jeśli nie, to jak bym stworzył taki alias lub funkcję w bash?

Jens Erat
źródło

Odpowiedzi:

31

W systemach linuxowych powinieneś mieć readlinkzainstalowany projekt GNU coreutils i możesz to zrobić:

readlink -f file.ext

W systemach Debian / ubuntu może być zainstalowane narzędzie realpath , które „zapewnia w większości te same funkcje, co /bin/readlink -fw pakiecie coreutils”.

Doug Harris
źródło
readlink -f(lub realpath, który jest starszym narzędziem zachowanym w celu zachowania zgodności) dodatkowo rozszerzy wszystkie dowiązania symboliczne, co niekoniecznie jest pożądane.
Gilles „SO- przestań być zły”
8
fyi: nie działa na macosxie.
akira,
Na moim komputerze Mac zainstalowałem Coreutils za pomocą HomeBrew i zawiera realpath.
Doug Harris
7

Zamiast pwdpolecenia użyj PWDzmiennej (również w POSIX):

fp () {
  case "$1" in
    /*) printf '%s\n' "$1";;
    *) printf '%s\n' "$PWD/$1";;
  esac
}

Jeśli potrzebujesz obsługi systemu Windows, rozpoznawanie ścieżek bezwzględnych będzie bardziej skomplikowane, ponieważ każdy port narzędzi uniksowych ma własne reguły tłumaczenia ścieżek plików. W Cygwin użyj cygpathnarzędzia.

Gilles „SO- przestań być zły”
źródło
Może to twój wybór, ale ta funkcja nie wyświetla nowej linii.
cyr
takie podejście ma tę zaletę, że wykorzystuje tylko wbudowane powłoki, co jest szybsze niż wywoływanie zewnętrznych plików binarnych. powinieneś wyjaśnić ten fakt nieco bardziej.
akira
4

aby odpowiedzieć na twoje pytanie za pomocą tego, czego używasz teraz:

alias rozwija się w miejscu, w którym teraz piszesz. wpisałeś:

% fp<SPACE>file.ext

to się staje

% echo `pwd`<SPACE>file.exe

możesz użyć funkcji, aby tego uniknąć:

function fp() {
    echo `pwd`/"$1"
}

możesz użyć tego jak zwykle:

% fp file.ext
akira
źródło
Potrzebujesz podwójnych cudzysłowów wokół podstawień zmiennych i poleceń:echo "`pwd`/$1"
Gilles 'SO- przestań być zły'
@Gilles: w jakich okolicznościach?
akira
2
@akira: Zawsze używaj podwójnych cudzysłowów, chyba że chcesz, aby wynik interpretacji był traktowany jako wzorzec globowania, a wyniki globbowania podzielone na słowa. Tutaj budujesz nazwę pojedynczego pliku, więc potrzebne są podwójne cudzysłowy (wypróbuj swoją funkcję z plikiem wywoływanym *w katalogu zawierającym inne pliki).
Gilles „SO- przestań być zły”
” jest globowane przez powłokę (w moim przypadku zsh) i rozszerzane, zanim wejdą w funkcję. fp *daje, /tmp/4cc3ea0c1b34bponieważ jest to pierwszy parametr funkcji. pozostałe parametry to inne pliki w katalogu. jak tylko mam plik o nazwie „ ” funkcja nadal działa zgodnie z oczekiwaniami, wywołując go za pomocą „*” lub * lub *
akira,
bash jest tutaj „zły”, jak się wydaje, bash daje to, o czym mówisz.
akira
3

Możesz użyć:

realpath file.ext
Cyrus
źródło
Nie mam tego. Skąd to pochodzi?
frabjous
@frabjous: jest specyficzny dla Debiana i pochodnych i zostanie zainstalowany tylko, jeśli o to poprosiłeś lub pakiet, który jest od niego zależny.
Gilles „SO- przestań być zły”
Używam Arch. To nie jest oparte na Debianie, ale i tak jest w nim pakiet. Nie jestem pewien, czy warto go zainstalować, jeśli mam już link do odczytu.
frabjous
Cóż, to jest opcja; lub możesz rozważyć funkcję, patrz odpowiedź Gillesa . W każdym razie zależy to od tego, jak naprawdę chcesz z tym skorzystać (jestem ciekawy).
cyr
@frabjous: Nie określiłeś systemu, na którym się znajdujesz, ale jeśli używa on menedżera pakietów opartego na Aptitude (Debian, Ubuntu, Mint, itp.), możesz wpisać, apt-cache search realpathaby ujawnić, że coreutils i zwykłe pakiety realpath oba zawierają to. Następnie możesz wpisać sudo apt-get install realpath(lub coreutils), aby go zainstalować.
Michael Scheper,
1

Od /programming//a/3915420/5795941

To jedyny sposób, który jest dla mnie do zaakceptowania. Nie rozwija linków takich jak realpath i readlink i jest to klasyczny sposób robienia tego, który widziałem wszędzie.

#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Philippe Carphin
źródło