Pytanie: czy istnieje prosta komenda sh / bash / zsh / fish / ... do wydrukowania ścieżki bezwzględnej dowolnego pliku, który ją podam?
Przypadek użycia: Jestem w katalogu /a/b
i chciałbym, aby wydrukować pełną ścieżkę do pliku c
w linii poleceń, dzięki czemu można łatwo wkleić go do innego programu: /a/b/c
. Prosty, ale niewielki program do tego może prawdopodobnie zaoszczędzić mi około 5 sekund, jeśli chodzi o obsługę długich ścieżek, co w końcu się sumuje. Zaskakuje mnie to, że nie mogę znaleźć standardowego narzędzia do zrobienia tego - czy tak naprawdę nie ma takiego?
Oto przykładowa implementacja, abspath.py:
#!/usr/bin/python
# Author: Diggory Hardy <[email protected]>
# Licence: public domain
# Purpose: print the absolute path of all input paths
import sys
import os.path
if len(sys.argv)>1:
for i in range(1,len(sys.argv)):
print os.path.abspath( sys.argv[i] )
sys.exit(0)
else:
print >> sys.stderr, "Usage: ",sys.argv[0]," PATH."
sys.exit(1)
Odpowiedzi:
Spróbować
realpath
.źródło
realpath
: github.com/westonruter/misc-cli-tools/blob/master/realpathSpróbuj
readlink
rozwiązać dowiązania symboliczne:źródło
-m
to najlepsza opcja do użycia./usr/bin/readlink
w Mavericks. A może miałeś na myśli, że tych opcji nie ma w systemie OS X? To wydaje się być karłowata wersja BSD ...: preadlink
podręcznika BSDonly the target of the symbolic link is printed. If the given argument is not a symbolic link, readlink will print nothing and exit with an error
:, więc readlink nie będzie działał w tym celu w OSXźródło
a b
(dwie spacje między aib, SO zjada jedną z nich).function realpath { echo $(cd $(dirname $1); pwd)/$(basename $1); }
sobierealpath
polecenie (obecnie akceptowana odpowiedź) w OS X. Dzięki!LOG=$(echo $(cd $(dirname $0); pwd)/$(basename $0 .sh).log)
Zapomnij o
readlink
irealpath
które mogą lub nie mogą być zainstalowane w systemie.Rozwijając powyższą odpowiedź dogbane, jest ona wyrażona jako funkcja:
możesz użyć go w następujący sposób:
Jak i dlaczego to działa?
Rozwiązanie wykorzystuje fakt, że wbudowane
pwd
polecenie Bash wyświetli bezwzględną ścieżkę do bieżącego katalogu, gdy zostanie wywołane bez argumentów.Dlaczego podoba mi się to rozwiązanie?
Jest przenośny i nie wymaga żadnego
readlink
lubrealpath
który często nie istnieje przy domyślnej instalacji danej dystrybucji Linux / Unix.Co jeśli dir nie istnieje?
Jak podano powyżej, funkcja zawiedzie i wydrukuje na stderr, jeśli podana ścieżka katalogu nie istnieje. To może nie być to, czego chcesz. Możesz rozwinąć funkcję, aby poradzić sobie z tą sytuacją:
Teraz zwróci pusty ciąg, jeśli katalog macierzysty nie istnieje.
Jak radzisz sobie ze znakami końcowymi „..” lub „.” na wejściu?
W takim przypadku daje to absolutną ścieżkę, ale nie minimalną. Będzie to wyglądać następująco:
Jeśli chcesz rozwiązać „..”, musisz wykonać skrypt w następujący sposób:
źródło
realpath
pochodzi z pakietu coreutils, który zawiera także narzędzia takie jakwho
,touch
lubcat
. Jest to dość standardowy zestaw narzędzi GNU, więc możesz być pewien, że jest on zainstalowany na prawie każdej maszynie opartej na systemie Linux. To powiedziawszy, masz rację: są 2 problemy z tym: i) prawdopodobnie przegapisz to podczas domyślnej instalacji na systemy uniksowe inne niż GNU (jak OpenBSD) ii) to narzędzie zostało wprowadzone w wersji 8.15 (więc jest całkiem nowe, od 2012 roku), więc będzie ci brakowało go w długoterminowych systemach stabilnych (takich jak RHEL 6).Jest to lepsze niż
readlink -e FILE
lubrealpath
, ponieważ działa, nawet jeśli plik nie istnieje.źródło
-m
opcja nie jest dostępna w Mavericks.Ta ścieżka względna do funkcji powłoki konwertera ścieżki bezwzględnej
cd
ipwd
)..
i.
Kod:
Próba:
Uwaga: jest to oparte na odpowiedziach nolan6000 i bsingh , ale naprawia wielkość pliku.
Rozumiem również, że pierwotne pytanie dotyczyło istniejącego narzędzia wiersza poleceń. Ale ponieważ wydaje się, że jest to pytanie dotyczące przepływu stosu, w tym skryptów powłoki, które chcą mieć minimalne zależności, umieściłem to rozwiązanie skryptu tutaj, aby móc je później znaleźć :)
źródło
$ abspath 'a b c/file.txt'
To dlatego, że argumentcd
to nie jest cytowany. Aby temu zaradzić, zamiast zacytować cały argument naecho
(czy jest powód tych cytatów?), Podaj tylko argumenty ścieżki. Tj zastąpićecho "$(cd ${1%/*}; pwd)/${1##*/}"
zecho $(cd "${1%/*}"; pwd)/${1##*/}
.echo "$(cd "$1"; pwd)"
go(cd "$1"; pwd)
. Nie ma tu potrzeby echa.( ... )
są nadal potrzebne, więccd
dzieje się to w podpowłoce, ponieważ nie chcemy zmieniać katalogu roboczego dla żadnych wywołującychabspath
.find
Komenda może pomócWyświetla listę wszystkich plików w bieżącym katalogu lub poniżej, z nazwami pasującymi do wzorca. Możesz to uprościć, jeśli uzyskasz tylko kilka wyników (np. Katalog u dołu drzewa zawierający kilka plików), tylko
Używam tego w systemie Solaris 10, który nie ma innych wymienionych narzędzi.
źródło
PWD
, możesz po prostu użyć$PWD/$filename
.Jeśli nie masz narzędzi readlink lub realpath, możesz użyć następującej funkcji, która działa w bash i zsh (nie jestem pewien co do reszty).
Działa to również w przypadku nieistniejących plików (podobnie jak funkcja python
os.path.abspath
).Niestety
abspath ./../somefile
nie pozbywa się kropek.źródło
echo "$1"
zprintf "%s\n" "$1"
(samo drugiego echa).echo
może interpretować ukośniki odwrotne w swoich argumentach.Oto funkcja tylko zsh, którą lubię ze względu na jej zwartość. Używa modyfikatora rozszerzenia „A” - patrz zshexpn (1).
źródło
Zasadniczo nie ma czegoś takiego jak do pliku (ten komunikat oznacza, że nie może być więcej niż jedna w ogóle, stąd korzystanie z określonego artykułu nie jest właściwe). Jest to dowolna ścieżka, która zaczyna się od katalogu głównego „/” i określa plik bez dwuznaczności niezależnie od katalogu roboczego. (Patrz na przykład wikipedia
absolute path
absolute path
).A
relative path
jest ścieżką, którą należy interpretować, zaczynając od innego katalogu. Może to być katalog roboczy, jeśli jest torelative path
manipulowany przez aplikację (choć niekoniecznie). Gdy znajduje się w dowiązaniu symbolicznym w katalogu, zwykle ma być względny w stosunku do tego katalogu (chociaż użytkownik może mieć na myśli inne zastosowania).Dlatego ścieżka bezwzględna jest po prostu ścieżką względem katalogu głównego.
Ścieżka (bezwzględna lub względna) może, ale nie musi, zawierać dowiązań symbolicznych. Jeśli tak nie jest, jest również nieco nieprzepuszczalny dla zmian w strukturze łączącej, ale nie jest to koniecznie wymagane, a nawet pożądane. Niektóre osoby nazywają
canonical path
(lubcanonical file name
lubresolved path
),absolute path
w których wszystkie dowiązania symboliczne zostały rozwiązane, tj. Zostały zastąpione ścieżką do dowolnego łącza. Poleceniarealpath
ireadlink
oba szukają ścieżki kanonicznej, alerealpath
ma tylko opcję uzyskania ścieżki bezwzględnej bez zawracania sobie głowy rozstrzyganiem dowiązań symbolicznych (wraz z kilkoma innymi opcjami uzyskania różnych rodzajów ścieżek, bezwzględnych lub względnych do jakiegoś katalogu).Wymaga to kilku uwag:
realpath
ireadlink
opcje do uwzględnienia tego.canonical
. Stąd koncepcja zależy od czasu (lub środowiska).canonical path
plik z dwóch powodów:ro
) w kilku punktach montowania.Dlatego nawet przy znacznie bardziej restrykcyjnej definicji
canonical path
pliku może istnieć kilka ścieżek kanonicznych. Oznacza to również, że kwalifikatorcanonical
jest nieco nieodpowiedni, ponieważ zwykle implikuje pojęcie wyjątkowości.To rozszerza krótką dyskusję na ten temat w odpowiedzi na inne podobne pytanie w Bash: pobrać ścieżkę bezwzględną podaną krewnemu
Mój wniosek jest taki, że
realpath
jest lepiej zaprojektowany i znacznie bardziej elastyczny niżreadlink
. Jedynym zastosowaniemreadlink
tego nie obejmujerealpath
połączenie bez opcji zwracającej wartość dowiązania symbolicznego.źródło
realpath
vs,readlink
a nawet linków symbolicznych są nadwyżką tego, o co prosiłem.canonical
odnosi się właśnie do tej wyjątkowości w stosunku do zestawu transformacji. Ale na przykład / dev / cdrom jest absolutnie dobrą ścieżką absolutną, nawet jeśli w rzeczywistości jest linkiem do / dev / sr0. Oba wskazują na to samo urządzenie. Moja pierwotna odpowiedź wskazywała na odpowiedni artykuł w sieci.dogbane
Odpowiedź z opisem, co nadchodzi na:Wyjaśnienie:
"$1"
dirname "$1"
cd "$(dirname "$1")
przechodzimy do tego względnego katalogu i uzyskujemy dla niego ścieżkę bezwzględną, uruchamiającpwd
polecenie powłoki$(basename "$1")
echo
to myźródło
Dla katalogów
dirname
zostaje wyzwolony../
i wraca./
.Funkcję nolan6000 można zmodyfikować, aby naprawić:
źródło
.profile
i dzięki temu dostępna do użytku interaktywnego.$1
jest to zwykła nazwa pliku:get_abs_filename foo
-> none (lub<current_dir>/foo/foo
jeślifoo
jest katalogiem).To nie jest odpowiedź na pytanie, ale dla tych, którzy wykonują skrypty:
poprawnie obsługuje / .. ./ itp. Wydaje mi się też, że pracuję na OSX
źródło
Umieściłem następujący skrypt w moim systemie i nazywam go jako alias bash, gdy chcę szybko pobrać pełną ścieżkę do pliku w bieżącym katalogu:
Nie jestem pewien, dlaczego, ale w OS X, gdy jest wywoływany przez skrypt „$ PWD” rozwija się do ścieżki bezwzględnej. Kiedy polecenie find jest wywoływane w wierszu poleceń, nie działa. Ale robi to, co chcę ... ciesz się.
źródło
$PWD
zawsze ma bezwzględną ścieżkę do katalogu roboczego. Ponadtofind
nie będzie tolerować ukośników, więc nie odpowiadasz na zadane pytanie. Szybszym sposobem na zrobienie tego, czego szukasz, byłby po prostuecho "$PWD/$1"
Najprostszym, jeśli chcesz używać tylko wbudowanych, jest prawdopodobnie:
Tylko dwa dodatkowe słowa do wpisania, i to będzie działać na wszystkich systemach uniksowych, a także OSX.
źródło
-maxdepth 1
wcześniej-name
(zakładając, że plik znajduje się w bieżącym katalogu). Bez tego będzie działać z plikami w dowolnym podkatalogu pwd, ale nie z innymi.find
że nie znajdzie pliku poza drzewem katalogów poniżejpwd
. Np. Jeśli spróbujeszfind . -name ../existingFile
, to się nie powiedzie.To uzupełnia wady
realpath
, przechowuj w skrypcie powłokifullpath
. Możesz teraz zadzwonić:źródło
realpath "foo bar"
->/home/myname/foo bar
. Jeśli nie możesz zawracać sobie głowy cytowaniem argumentów wiersza poleceń, to nierealpath
jest wina.Alternatywą dla uzyskania ścieżki absolutnej w Ruby :
realpath() {ruby -e "require 'Pathname'; puts Pathname.new('$1').realpath.to_s";}
Działa bez argumentów (bieżący folder) i względną i bezwzględną ścieżkę do pliku lub folderu jako agument.
źródło
Odpowiedz z Homebrew
realpath
jest najlepszą odpowiedzią, ale jeśli nie masz go zainstalowanego, musisz najpierw uruchomić,brew install coreutils
aby zainstalować coreutils z wieloma niesamowitymi funkcjami. Pisanie niestandardowej funkcji i eksportowanie jej to zbyt wiele pracy i ryzyko błędu w przypadku czegoś takiego, oto dwie linie:źródło
Hej chłopaki, wiem, że to stary wątek, ale zamieszczam to w celach informacyjnych dla każdego, kto odwiedził to, jak ja. Jeśli dobrze zrozumiałem pytanie, myślę, że
locate $filename
polecenie. Wyświetla bezwzględną ścieżkę do dostarczonego pliku, ale tylko jeśli istnieje.źródło
locate
to narzędzie do wyszukiwania plików / ścieżek według nazwy. Może wykonać zadanie, ale może również znaleźć inne dopasowania i może nie znaleźć istniejącego pliku bez uprzedniego wywołaniaupdatedb
jako root.