polecenie bash / fish, aby wydrukować ścieżkę bezwzględną do pliku

448

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/bi chciałbym, aby wydrukować pełną ścieżkę do pliku cw 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)
opóźnione
źródło
Argumentowałbym, że odpowiedź @ DennisWilliamson (użycie opcji -m) jest lepsza, ponieważ (zwykle) jest bardziej przenośna i pracuje z plikami, które nie istnieją.
TTT,
Lub odpowiedź Flimma; oba są dobrymi rozwiązaniami. Jednak Bannier najlepiej odpowiada na moje pierwotne pytanie.
opóźniony
3
Użytkownicy OSX: zobacz tę odpowiedź
Ian

Odpowiedzi:

562

Spróbować realpath.

$ realpath example.txt
/home/username/example.txt
Benjamin Bannier
źródło
133
+1, bardzo fajny program. Należy jednak pamiętać, że jest to polecenie zewnętrzne (nie wbudowane w powłokę) i może domyślnie nie być obecne w każdym systemie, tzn. Może być konieczne jego zainstalowanie. W Debianie znajduje się w osobnym pakiecie o tej samej nazwie.
Roman Cheplyaka,
5
Do mojej ścieżki dodałemrealpath : github.com/westonruter/misc-cli-tools/blob/master/realpath
Weston Ruter
1
@Flimm: Nadal da ci prawidłową ścieżkę, biorąc pod uwagę ścieżkę względną. Jeśli chcesz wiedzieć o istnieniu pliku, użyj innego narzędzia, takiego jak np. Test.
Benjamin Bannier
14
@Dalin: Spróbuj zainstalować coreutils. Plik binarny nosi nazwę grealpath.
Toni Penya-Alba
5
To narzędzie zostało wprowadzone w GNU coreutils 8.15 (w 2012 roku), więc jest całkiem nowe.
marbu
319

Spróbuj readlinkrozwiązać dowiązania symboliczne:

readlink -e /foo/bar/baz
Wstrzymano do odwołania.
źródło
50
Wolę użyć „-f” zamiast „-e”, abyśmy mogli zobaczyć bezwzględną ścieżkę nieistniejącego pliku.
hluk
5
Dla mnie wygląda to na najprostsze, a jednocześnie jest przenośne. readlink jest portem jądra GNU, więc zostanie zainstalowany na prawie każdej dystrybucji Linuksa, z wyjątkiem niektórych osadzonych.
catphive
14
Wydaje mi się, że -mto najlepsza opcja do użycia.
Matt Joiner
1
@Dalin: /usr/bin/readlinkw 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 ...: p
iconoclast
14
@iconoclast Te opcje nie są dostępne w OSX i jak na stronie readlinkpodręcznika BSD only 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
SnoringFrog
257
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
dogbane
źródło
8
Nie zapomnij zacytować wszystkich rzeczy. Jeśli nie rozumiesz dlaczego, wypróbuj swój program na pliku a b(dwie spacje między aib, SO zjada jedną z nich).
Roman Cheplyaka,
1
spróbuj także tego na „/”, zamienia się w „///”
George
35
jedynym rozwiązaniem POSIX tak daleko, że nie wymaga się pisać i skompilować plik wykonywalny od readlink i realpath nie są POSIX
Ciro Santilli郝海东冠状病六四事件法轮功
25
Kiedyś robiłem function realpath { echo $(cd $(dirname $1); pwd)/$(basename $1); }sobie realpathpolecenie (obecnie akceptowana odpowiedź) w OS X. Dzięki!
James Bedford
1
Użyłem tej metody do zdefiniowania nazw plików dziennika dla skryptów:LOG=$(echo $(cd $(dirname $0); pwd)/$(basename $0 .sh).log)
DrStrangepork
85

Zapomnij o readlinki realpathktóre mogą lub nie mogą być zainstalowane w systemie.

Rozwijając powyższą odpowiedź dogbane, jest ona wyrażona 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 pwdpolecenie 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 readlinklub realpathktó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ą:

#!/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 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:

/Users/bob/Documents/..

Jeśli chcesz rozwiązać „..”, musisz wykonać skrypt w następujący sposób:

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
}
Peter
źródło
Fajna funkcja, ale najwyraźniej nie rozumiesz pytania. Chciałem czegoś do użytku interaktywnego, a nie skryptów.
opóźniony
3
Chciałbym dodać, że realpathpochodzi z pakietu coreutils, który zawiera także narzędzia takie jak who, touchlub cat. 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).
marbu
1
Wydaje się, że przynajmniej Continuum Analytics (twórcy dystrybucji Anaconda Python ) podobała się ta odpowiedź. Jest on zaimplementowany (z odnośnikiem odsyłającym tutaj) w skrypcie „aktywuj” , który służy do aktywacji środowisk wirtualnych utworzonych przez narzędzie conda. Więc… dobry!
wjv
1
Działa to tylko dla katalogów (ponieważ nie ma nic innego) i nie radzi sobie z „..” i „.”. Zobacz moją odpowiedź, która powinna obsłużyć wszystko: stackoverflow.com/a/23002317/2709
Alexander Klimetschek
3
@marbu realpath nie jest obecny na Ubuntu 14.04 ani na Debian Wheezy. Z czasem może stać się standardem, ale na pewno nie teraz. Zauważ też, że OP nie powiedział nic o Linuksie ani GNU. Bash jest szerzej stosowany.
mc0e
77
$ readlink -m FILE
/path/to/FILE

Jest to lepsze niż readlink -e FILElub realpath, ponieważ działa, nawet jeśli plik nie istnieje.

Flimm
źródło
Miły. Działa to również w przypadku plików / katalogów, które istnieją, ale nie są dowiązaniami symbolicznymi.
quietmint,
Mam link do odczytu dostępny w systemie OS X 10.9 (Mavericks), więc jest to zdecydowanie najlepsza odpowiedź tutaj.
Kenneth Hoste
6
@KennethHoste: -mopcja nie jest dostępna w Mavericks.
iconoclast
2
Zdecydowanie nie jest to na DOMYŚLNEJ instalacji OSX.
Fran Marzoa,
działa na Linuksie (CentOS) dziękuję, ponieważ realpath nie istniał dla niego
jimh
66

Ta ścieżka względna do funkcji powłoki konwertera ścieżki bezwzględnej

  • nie wymaga narzędzi (tylko cdi pwd)
  • działa dla katalogów i plików
  • uchwyty ..i.
  • obsługuje spacje w nazwach katalogów lub plików
  • wymaga, aby plik lub katalog istniał
  • nic nie zwraca, jeśli nic nie istnieje na danej ścieżce
  • obsługuje ścieżki bezwzględne jako dane wejściowe (zasadniczo je przekazuje)

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óba:

# 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 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źć :)

Alexander Klimetschek
źródło
Dzięki. Właśnie z tym korzystam na OSX
Greg
Nie działa to w przypadku katalogów ze spacjami, tj .: $ abspath 'a b c/file.txt'To dlatego, że argument cdto nie jest cytowany. Aby temu zaradzić, zamiast zacytować cały argument na echo(czy jest powód tych cytatów?), Podaj tylko argumenty ścieżki. Tj zastąpić echo "$(cd ${1%/*}; pwd)/${1##*/}"z echo $(cd "${1%/*}"; pwd)/${1##*/}.
George
@george Dzięki za uwagę, naprawiłem to.
Alexander Klimetschek
1
Przejrzałem dziesiątki rozwiązań na wpół przechylonych i to zdecydowanie wydaje się być najbardziej zwięzłym i dokładnym rozwiązaniem opartym tylko na bashu. Możesz go jeszcze bardziej wyszczuplić, zastępując echo "$(cd "$1"; pwd)"go (cd "$1"; pwd). Nie ma tu potrzeby echa.
Sześć
@Six True, zaktualizowano. Nawiasy klamrowe ( ... )są nadal potrzebne, więc cddzieje się to w podpowłoce, ponieważ nie chcemy zmieniać katalogu roboczego dla żadnych wywołujących abspath.
Alexander Klimetschek
24

findKomenda może pomóc

find $PWD -name ex*
find $PWD -name example.log

Wyś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

find $PWD

Używam tego w systemie Solaris 10, który nie ma innych wymienionych narzędzi.

lessthanideal
źródło
1
nie przeczytałem tego komentarza przy pierwszym czytaniu; kluczową kwestią jest to, że jeśli podasz bezwzględną ścieżkę do polecenia find, to spowoduje to, że wynik będzie w postaci bezwzględnej ścieżki. więc użycie $ PWD jest absolutną ścieżką miejsca, w którym się znajdujesz, więc otrzymujesz wynik jako absolutny.
simbo1905
4
Jeśli polegasz PWD, możesz po prostu użyć $PWD/$filename.
jonny
Podejście to można ulepszyć za pomocą opcji -maxdepth 1. Nie zapominaj także o cytowaniu - potencjalnych problemach z bezpieczeństwem, w zależności od tego, jak tego używasz.
mc0e
1
@jonny: $ PWD / $ nazwa_pliku kończy się niepowodzeniem, jeśli $ nazwa_pliku jest już absolutna.
mc0e
Nie powiedzie się to, jeśli nazwa pliku zostanie podana jako „./filename.txt” (z kropką i ukośnikiem).
Mark Stosberg
15

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ż w przypadku nieistniejących plików (podobnie jak funkcja python os.path.abspath).

Niestety abspath ./../somefilenie pozbywa się kropek.

hluk
źródło
1
Wygląda mi przenośnie. Z drugiej strony, popsuje się na przykład na nazwie pliku zawierającej nowy wiersz.
Roman Cheplyaka,
1
W celu dalszej poprawy wymienić echo "$1"z printf "%s\n" "$1"(samo drugiego echa). echomoże interpretować ukośniki odwrotne w swoich argumentach.
Roman Cheplyaka,
Znowu masz rację! Naprawdę zachowanie polecenia echo w zsh różni się od bash.
hluk
1
Ściśle mówiąc, w POSIX zachowanie echa jest niezdefiniowane, jeśli argumenty zawierają ukośniki odwrotne. Jest to jednak zdefiniowane w rozszerzeniu XSI (echo powinno interpretować sekwencje specjalne). Ale zarówno bash, jak i zsh są tak dalekie od zgodności z POSIX ...
Roman Cheplyaka,
Przepraszam, ale nie widzę sensu. Podałem już odpowiedź jako skrypt z większą liczbą funkcji i nie trzeba jej używać w skrypcie powłoki.
opóźniony
10

Oto funkcja tylko zsh, którą lubię ze względu na jej zwartość. Używa modyfikatora rozszerzenia „A” - patrz zshexpn (1).

realpath() { for f in "$@"; do echo ${f}(:A); done }
wjv
źródło
Wow, to eleganckie rozwiązanie !!
ShellFish,
6

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 pathabsolute path ).

A relative pathjest ś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(lub canonical file namelub resolved path), absolute pathw których wszystkie dowiązania symboliczne zostały rozwiązane, tj. Zostały zastąpione ścieżką do dowolnego łącza. Polecenia realpathi readlinkoba szukają ścieżki kanonicznej, ale realpathma 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:

  1. dowiązania symboliczne można rozwiązać tylko wtedy, gdy coś, z czym mają się połączyć, jest już utworzone, co oczywiście nie zawsze ma miejsce. Polecenia realpathi readlinkopcje do uwzględnienia tego.
  2. katalog na ścieżce może później stać się dowiązaniem symbolicznym, co oznacza, że ​​ścieżka już nie jest canonical. Stąd koncepcja zależy od czasu (lub środowiska).
  3. nawet w idealnym przypadku, gdy wszystkie dowiązania symboliczne można rozwiązać, nadal może być więcej niż jeden canonical pathplik z dwóch powodów:
    • partycja zawierająca plik mogła zostać zamontowana jednocześnie ( ro) w kilku punktach montowania.
    • mogą istnieć twarde linki do pliku, co oznacza, że ​​plik istnieje w kilku różnych katalogach.

Dlatego nawet przy znacznie bardziej restrykcyjnej definicji canonical pathpliku może istnieć kilka ścieżek kanonicznych. Oznacza to również, że kwalifikator canonicaljest 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 realpathjest lepiej zaprojektowany i znacznie bardziej elastyczny niż readlink. Jedynym zastosowaniem readlinktego nie obejmuje realpathpołączenie bez opcji zwracającej wartość dowiązania symbolicznego.

Babou
źródło
Nie przeszkadza mi, że jestem zaniedbany, ale lubię rozumieć, dlaczego mogę się czegoś nauczyć, zarówno technicznego, jak i tego, co jest uważane za właściwą praktykę na stronie. Cóż ... przynajmniej skłoniło mnie do zarejestrowania się w Meta Stack Overflow, aby lepiej zrozumieć lokalną socjologię. Polecam to. - Mimo to, jeśli ktoś ma opinię na temat niewłaściwości mojej odpowiedzi, jestem zainteresowany.
babou
1
(a) pytanie ma prawidłową odpowiedź sprzed 2 + 1/2 lat, (b) istnieje (pojedyncza) ścieżka bezwzględna odpowiadająca ścieżce względnej (to jest to, czego chciałem), ale może nie do pliku takiego jak ty wskazany. BTW wszelkie komentarze na temat realpathvs, readlinka nawet linków symbolicznych są nadwyżką tego, o co prosiłem.
opóźniony
1
Drugi komentarz: krótkie odpowiedzi są bardzo często bardziej przydatne niż długie wykłady. Przepełnienie stosu jest zwykle używane do zadawania określonych pytań.
opóźniony
5
1- fakt, że pytanie ma prawidłową odpowiedź przez jakkolwiek długi czas, nie oznacza, że ​​jest zamknięte. Pytania nie są przeznaczone wyłącznie do użytku osobistego. Rzeczywiście istnieją odznaki dla odpowiedzi, które zbierają więcej głosów niż potwierdzona odpowiedź. Dzięki nowym narzędziom „najlepsza” odpowiedź może z czasem ulec zmianie. Wiele osób korzysta ze starych odpowiedzi dostępnych za pośrednictwem wyszukiwania w sieci.
babou
1
2 - Nalegasz, aby istniała (pojedyncza) ścieżka bezwzględna odpowiadająca ścieżce względnej . Chociaż domyślam się, co masz na myśli przez „odpowiadanie”, tj. Ścieżkę pochodzącą z oryginału poprzez dany zestaw transformacji, twoje zdanie jest nadal niepoprawne. Istnieje unikalna „odpowiednia” ścieżka kanoniczna. Słowo canonicalodnosi 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.
babou
5

dogbane Odpowiedź z opisem, co nadchodzi na:

#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"

Wyjaśnienie:

  1. Ten skrypt pobiera ścieżkę względną jako argument "$1"
  2. Następnie otrzymujemy dirname część tej ścieżki (możesz przekazać katalog lub plik do tego skryptu):dirname "$1"
  3. Następnie cd "$(dirname "$1")przechodzimy do tego względnego katalogu i uzyskujemy dla niego ścieżkę bezwzględną, uruchamiając pwdpolecenie powłoki
  4. Następnie dodajemy basename do ścieżki bezwzględnej:$(basename "$1")
  5. Jako ostatni krok echoto my
Eugen Konkov
źródło
2

Dla katalogów dirnamezostaje wyzwolony ../i wraca ./.

Funkcję nolan6000 można zmodyfikować, aby naprawić:

get_abs_filename() {
  # $1 : relative filename
  if [ -d "${1%/*}" ]; then
    echo "$(cd ${1%/*}; pwd)/${1##*/}"
  fi
}
bsingh
źródło
1
Witamy w SO! W przypadku drobnych zmian i uwag dodanie komentarza do istniejącej odpowiedzi może być bardziej odpowiednie niż dodanie odpowiedzi, zwłaszcza jeśli ta skopiowana odpowiedź nie zawiera wielu innych informacji z oryginalnej odpowiedzi. Po zebraniu nieco większej reputacji możesz dodawać komentarze do odpowiedzi innych osób. Na razie staraj się zbierać reputację, zadając unikalne, cenne pytania lub udzielając samodzielnych, dobrych odpowiedzi.
cfi
1
Ponieważ odwołujesz się do odpowiedzi nolan6000, zwróć uwagę, że plakat dardy już skomentował, że nie zaakceptuje odpowiedzi nolan6000, ponieważ nie szuka skryptu. Tak ściśle mówiąc, twoja odpowiedź nie odpowiada na pytanie.
cfi
funkcja może zostać dodana .profilei dzięki temu dostępna do użytku interaktywnego.
adib
To nie zadziała, jeśli $1jest to zwykła nazwa pliku: get_abs_filename foo-> none (lub <current_dir>/foo/foojeśli foojest katalogiem).
ivan_pozdeev
2

To nie jest odpowiedź na pytanie, ale dla tych, którzy wykonują skrypty:

echo `cd "$1" 2>/dev/null&&pwd||(cd "$(dirname "$1")";pwd|sed "s|/*\$|/${1##*/}|")`

poprawnie obsługuje / .. ./ itp. Wydaje mi się też, że pracuję na OSX

Alek
źródło
2

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:

#!/bin/bash
/usr/bin/find "$PWD" -maxdepth 1 -mindepth 1 -name "$1"

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ę.

fred.johnsen
źródło
$PWDzawsze ma bezwzględną ścieżkę do katalogu roboczego. Ponadto findnie 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"
Adam Katz,
2

Najprostszym, jeśli chcesz używać tylko wbudowanych, jest prawdopodobnie:

find `pwd` -name fileName

Tylko dwa dodatkowe słowa do wpisania, i to będzie działać na wszystkich systemach uniksowych, a także OSX.

Arj
źródło
Dodałbym -maxdepth 1wcześ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.
Walter Tross
Rzeczywiście masz rację, pytanie określa, że ​​plik będzie w bieżącym katalogu. Co masz na myśli mówiąc „ale nie z innymi”?
Arj
Mam na myśli, findże nie znajdzie pliku poza drzewem katalogów poniżej pwd. Np. Jeśli spróbujesz find . -name ../existingFile, to się nie powiedzie.
Walter Tross
W porządku, tak, to zakładałoby, że chcesz wydrukować pełną ścieżkę pliku na dysku CD (jak w oryginalnym pytaniu) lub w dowolnym miejscu w drzewie cwd (nie w oryginalnym pytaniu).
Arj
1
#! /bin/bash

file="$@"
realpath "$file" 2>/dev/null || eval realpath $(echo $file | sed 's/ /\\ /g')

To uzupełnia wady realpath, przechowuj 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.
Skorupiak
źródło
Co to rozwiązuje? realpath "foo bar"-> /home/myname/foo bar. Jeśli nie możesz zawracać sobie głowy cytowaniem argumentów wiersza poleceń, to nie realpathjest wina.
ivan_pozdeev
Uzgodniono, że jest to raczej opakowanie na wygodę.
ShellFish,
1

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.

Atika
źródło
0

Odpowiedz z Homebrew

realpathjest najlepszą odpowiedzią, ale jeśli nie masz go zainstalowanego, musisz najpierw uruchomić, brew install coreutilsaby 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:

$ brew install coreutils
$ realpath your-file-name.json 
Zorayr
źródło
-1

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 $filenamepolecenie. Wyświetla bezwzględną ścieżkę do dostarczonego pliku, ale tylko jeśli istnieje.

icyyd
źródło
4
locateto 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łania updatedbjako root.
dhardy