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)
Author: dhardy, 2010-10-12

17 answers

Spróbuj realpath.

~ $ realpath example.txt
/home/username/example.txt
 351
Author: Benjamin Bannier,
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
 281
Author: Dennis Williamson,
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")"
 194
Author: dogbane,
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.

 72
Author: Flimm,
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
}
 68
Author: peterh,
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 i pwd)
  • 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 :)

 55
Author: Alexander Klimetschek,
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.

 23
Author: lessthanideal,
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.

 14
Author: hluk,
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 }
 9
Author: wjv,
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:

  1. 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 i readlink mają opcje, aby to uwzględnić.
  2. 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).
  3. 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.

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.

 8
Author: babou,
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
}
 3
Author: bsingh,
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.

 3
Author: fred.johnsen,
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:

  1. ten skrypt otrzymuje ścieżkę względną jako argument "$1"
  2. następnie otrzymujemy dirname część tej ścieżki (możesz przekazać do tego skryptu katalog lub plik): dirname "$1"
  3. następnie cd "$(dirname "$1") do tego względnego katalogu i uzyskujemy dla niego ścieżkę absolutną, uruchamiając pwd polecenie powłoki
  4. następnie dodajemy basename do ścieżki absolutnej: $(basename "$1")
  5. jako ostatni krok my echo to
 2
Author: Eugen Konkov,
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.
 1
Author: ShellFish,
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

 1
Author: Alek,
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.

 1
Author: Atika,
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.

 -1
Author: icyyd,
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