polecenie bash / fish do wypisania bezwzględnej ścieżki do pliku
Pytanie: czy istnieje prosty sh / bash/zsh/fish/... polecenie wypisania bezwzględnej ścieżki pliku, który go przesyłam?
Przypadek użycia: znajduję się w katalogu /a/b
i chciałbym wydrukować pełną ścieżkę do pliku c
w wierszu poleceń, aby łatwo wkleić ją do innego programu: /a/b/c
. Prosty, ale mały program do tego mógłby zaoszczędzić mi około 5 sekund, jeśli chodzi o obsługę długich ścieżek, co w końcu się sumuje. Dziwi mnie więc, że nie mogę znaleźć standardowego narzędzia do zrób to-czy naprawdę nie ma?
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)
17 answers
Spróbuj realpath
.
~ $ realpath example.txt
/home/username/example.txt
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-29 10:29:34
Spróbuj readlink
, które rozwiąże dowiązania symboliczne:
readlink -e /foo/bar/baz
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-12 14:34:06
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-05 07:51:05
$ readlink -m FILE
/path/to/FILE
Jest to lepsze niż readlink -e FILE
lub realpath
, ponieważ działa nawet jeśli plik nie istnieje.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-27 17:10:00
Zapomnij o readlink
i realpath
, które mogą lub nie mogą być zainstalowane w Twoim systemie.
Rozszerzenie na odpowiedź dogbane ' a powyżej wyrażona jest jako funkcja:
#!/bin/bash
get_abs_filename() {
# $1 : relative filename
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
}
Możesz użyć go w następujący sposób:
myabsfile=$(get_abs_filename "../../foo/bar/file.txt")
Jak i dlaczego to działa?
Rozwiązanie wykorzystuje fakt, że wbudowane w Bash polecenie pwd
wyświetli bezwzględną ścieżkę bieżącego katalogu, gdy zostanie wywołane bez argumentów.
Dlaczego podoba mi się to rozwiązanie ?
Jest przenośny i nie wymaga ani readlink
ani realpath
, które często nie istnieją w domyślnej instalacji danej dystrybucji Linuksa / Unixa.
Co jeśli dir nie istnieje?
Jak podano powyżej, funkcja nie powiedzie się i zostanie wydrukowana na stderr, jeśli podana ścieżka do katalogu nie istnieje. Może nie tego chcesz. Możesz rozwinąć funkcję, aby poradzić sobie z tą sytuacją:
#!/bin/bash
get_abs_filename() {
# $1 : relative filename
if [ -d "$(dirname "$1")" ]; then
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
fi
}
Teraz zwróci pusty łańcuch, jeśli jeden rodzic dirs nie istnieć.
Jak sobie radzisz?."lub"."in input ?
Cóż, w tym przypadku daje to ścieżkę absolutną, ale nie minimalną. Będzie wyglądał tak:
/Users/bob/Documents/..
Jeśli chcesz rozwiązać '.."musisz zrobić skrypt jak:
get_abs_filename() {
# $1 : relative filename
filename=$1
parentdir=$(dirname "${filename}")
if [ -d "${filename}" ]; then
echo "$(cd "${filename}" && pwd)"
elif [ -d "${parentdir}" ]; then
echo "$(cd "${parentdir}" && pwd)/$(basename "${filename}")"
fi
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-24 20:55:47
Ten względny konwerter ścieżki do ścieżki absolutnej funkcja powłoki
- nie wymaga żadnych narzędzi (tylko
cd
ipwd
) - Działa dla katalogów i plików
- uchwyty
..
i.
- obsługuje spacje w katalogu lub nazwach plików
- wymaga istnienia pliku lub katalogu
- zwraca nic, jeśli nic nie istnieje na podanej ścieżce
- obsługuje ścieżki bezwzględne jako wejście (przekazuje je przez zasadniczo)
Kod:
function abspath() {
# generate absolute path from relative path
# $1 : relative filename
# return : absolute path
if [ -d "$1" ]; then
# dir
(cd "$1"; pwd)
elif [ -f "$1" ]; then
# file
if [[ $1 = /* ]]; then
echo "$1"
elif [[ $1 == */* ]]; then
echo "$(cd "${1%/*}"; pwd)/${1##*/}"
else
echo "$(pwd)/$1"
fi
fi
}
Próbka:
# assume inside /parent/cur
abspath file.txt => /parent/cur/file.txt
abspath . => /parent/cur
abspath .. => /parent
abspath ../dir/file.txt => /parent/dir/file.txt
abspath ../dir/../dir => /parent/dir # anything cd can handle
abspath doesnotexist => # empty result if file/dir does not exist
abspath /file.txt => /file.txt # handle absolute path input
uwaga: jest to oparte na odpowiedziach Z nolan6000 i bsingh , ale naprawia przypadek pliku.
Rozumiem również, że pierwotne pytanie dotyczyło istniejącego narzędzia wiersza poleceń. Ale ponieważ wydaje się, że jest to pytanie na stackoverflow dla tego, w tym skryptów powłoki, które chcą mieć minimalne zależności, umieściłem to rozwiązanie skrypt tutaj, więc mogę go znaleźć później :)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-20 20:48:55
Polecenie find
może pomóc
find $PWD -name ex*
find $PWD -name example.log
Wyświetla listę wszystkich plików w bieżącym katalogu lub pod nim z nazwami pasującymi do wzorca. Możesz to uprościć, jeśli uzyskasz tylko kilka wyników (np. katalog na dole drzewa zawierający kilka plików), po prostu
find $PWD
Używam tego na Solaris 10, który nie ma innych narzędzi wymienionych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-03 13:36:37
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).
abspath () { case "$1" in /*)printf "%s\n" "$1";; *)printf "%s\n" "$PWD/$1";; esac; }
Działa to również dla nieistniejących plików(podobnie jak funkcja Pythona os.path.abspath
).
Niestety abspath ./../somefile
nie pozbywa się kropek.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-12 18:28:01
Oto jedyna funkcja zsh, którą lubię za jej zwartość. Używa modyfikatora rozszerzenia 'A' - patrz zshexpn(1).
realpath() { for f in "$@"; do echo ${f}(:A); done }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-24 13:59:37
Generalnie nie ma czegoś takiego jak absolute path
do pliku (stwierdzenie to oznacza, że może być więcej niż jeden w ogóle, stąd użycie określonego artykułu nie jest właściwe). absolute path
jest dowolną ścieżką rozpoczynającą się od głównego "/" i oznaczającą plik bez niejednoznaczności niezależnie od katalogu roboczego.(patrz na przykład wikipedia ).
A relative path
jest ścieżką, która ma być interpretowana począwszy od innego katalogu. Może to być katalog roboczy, jeśli jest relative path
manipulowany przez aplikację
(choć niekoniecznie). Gdy znajduje się w dowiązaniu symbolicznym w katalogu, zazwyczaj ma być względem tego katalogu (choć użytkownik może mieć na uwadze inne zastosowania).
Stąd ścieżka absolutna jest tylko ścieżką względem katalogu głównego.
Ścieżka (absolutna lub względna) może lub nie może zawierać dowiązań symbolicznych. Jeśli nie, jest również nieco odporny na zmiany w strukturze łączenia, ale nie jest to koniecznie wymagane lub nawet pożądane. Niektóre osoby wywołują canonical path
(lub canonical file name
lub resolved path
) absolute path
, w którym wszystkie dowiązania symboliczne zostały rozwiązane, tzn. zostały zastąpione ścieżką do miejsca, do którego się łączą. Polecenia realpath
i readlink
szukają kanonicznej ścieżki, ale tylko realpath
ma opcję uzyskania ścieżki absolutnej bez rozwiązywania dowiązań symbolicznych (wraz z kilkoma innymi opcjami uzyskania różnych ścieżek, bezwzględnych lub względnych katalog).
To wymaga kilku uwag:
- dowiązania symboliczne mogą być rozwiązywane tylko wtedy, gdy mają być
link do jest już utworzony, co oczywiście nie zawsze ma miejsce. Polecenia
realpath
ireadlink
mają opcje, aby to uwzględnić. - katalog na ścieżce może później stać się dowiązaniem symbolicznym, co oznacza, że ścieżka nie jest już
canonical
. Stąd pojęcie jest zależne od czasu (lub środowiska). - nawet w idealnym przypadku, gdy wszystkie dowiązania symboliczne mogą być rozwiązywane,
do pliku może być jeszcze więcej niż jeden
canonical path
, dla dwóch uzasadnienie:- partycja zawierająca plik mogła być montowana jednocześnie (
ro
) w kilku punktach montowania. - mogą istnieć twarde łącza do pliku, co oznacza, że plik istnieje w kilku różnych katalogach.
- partycja zawierająca plik mogła być montowana jednocześnie (
Stąd, nawet przy znacznie bardziej restrykcyjnej definicji canonical path
, może istnieć kilka kanonicznych ścieżek do pliku. To także oznacza to, że kwalifikator canonical
jest nieco nieodpowiedni, ponieważ zwykle implikuje pojęcie wyjątkowości.
To rozszerza krótkie omówienie tematu w odpowiedzi na inne podobne pytanie w Bash: pobieranie bezwzględnej ścieżki podanej względnie
Mój wniosek jest taki, że realpath
jest lepiej zaprojektowany i znacznie bardziej elastyczny niż readlink
.
Jedynym zastosowaniem readlink
, które nie jest objęte realpath
, jest wywołanie bez opcji zwracającej wartość dowiązania symbolicznego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:54
Dla katalogów dirname
zostaje potknięty dla ../
i zwraca ./
.
Funkcja Nolan6000 może być zmodyfikowana, aby naprawić, że:
get_abs_filename() {
# $1 : relative filename
if [ -d "${1%/*}" ]; then
echo "$(cd ${1%/*}; pwd)/${1##*/}"
fi
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:11
Umieściłem następujący skrypt w moim systemie i nazywam go aliasem bash, gdy chcę szybko pobrać pełną ścieżkę do pliku w bieżącym katalogu:
#!/bin/bash
/usr/bin/find "$PWD" -maxdepth 1 -mindepth 1 -name "$1"
Nie jestem pewien dlaczego, ale na OS X wywołany skryptem "$ PWD " rozszerza się do ścieżki absolutnej. Gdy polecenie find jest wywoływane w linii poleceń, nie robi tego. ale robi to, co chcę... smacznego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-21 05:50:28
The dogbane
odpowiedź z opisem co się dzieje:
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
Wyjaśnienie:
- ten skrypt otrzymuje ścieżkę względną jako argument
"$1"
- następnie otrzymujemy dirname część tej ścieżki (możesz przekazać do tego skryptu katalog lub plik):
dirname "$1"
- następnie
cd "$(dirname "$1")
do tego względnego katalogu i uzyskujemy dla niego ścieżkę absolutną, uruchamiającpwd
polecenie powłoki - następnie dodajemy basename do ścieżki absolutnej:
$(basename "$1")
- jako ostatni krok my
echo
to
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:47
#! /bin/bash
file="$@"
realpath "$file" 2>/dev/null || eval realpath $(echo $file | sed 's/ /\\ /g')
To nadrabia braki realpath
, przechowuj je w skrypcie powłoki fullpath
. Możesz teraz zadzwonić:
$ cd && touch a\ a && rm A 2>/dev/null
$ fullpath "a a"
/home/user/a a
$ fullpath ~/a\ a
/home/user/a a
$ fullpath A
A: No such file or directory.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-19 11:53:39
To nie jest odpowiedź na pytanie, ale dla tych, którzy robią Skrypty:
echo `cd "$1" 2>/dev/null&&pwd||(cd "$(dirname "$1")";pwd|sed "s|/*\$|/${1##*/}|")`
Obsługuje / .. ./ etc poprawnie. Wydaje mi się, że również pracuję na OSX
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-16 18:57:03
Alternatywa dla uzyskania ścieżki bezwzględnej w Ruby :
realpath() {ruby -e "require 'Pathname'; puts Pathname.new('$1').realpath.to_s";}
Działa bez argumentów (bieżący folder) oraz względnej i bezwzględnej ścieżki pliku lub folderu jako agument.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-10 16:16:06
Hej chłopaki wiem, że to stary wątek, ale po prostu zamieszczam to w odniesieniu do każdego, kto odwiedził to tak jak ja. Jeśli dobrze zrozumiałem pytanie, myślę, że komenda locate $filename
. Wyświetla bezwzględną ścieżkę dostarczonego pliku, ale tylko wtedy, gdy istnieje.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-05 12:01:05