cytaty w środku są ważne, inaczej stracisz wszystkie swoje dane
catamphetamine
10
i wariant, którego używam, aby uzyskać element nadrzędny bieżącego katalogu roboczego: parentdir=$(dirname `pwd`)
TheGrimmScientist
3
Uwaga: ta metoda nie jest bezpieczna w przypadku „brzydkich” nazw. Nazwa taka jak „-rm -rf” złamie pożądane zachowanie. Prawdopodobnie "." też. Nie wiem, czy to najlepszy sposób, ale stworzyłem tutaj osobne pytanie „skoncentrowane na poprawności”: stackoverflow.com/questions/40700119/…
VasiliNovikov
4
@Christopher Shroba Tak, pominąłem cytaty, a potem mój dysk twardy został częściowo wyczyszczony. Nie pamiętam dokładnie, co się wydarzyło: prawdopodobnie niecytowany katalog z białymi odstępami spowodował usunięcie katalogu nadrzędnego zamiast katalogu docelowego - mój skrypt właśnie skasował folder / home / xxx /.
katamfetamina
3
o dobrze, więc nie ma nic w poleceniu, które spowodowałoby utratę danych, chyba że wydałeś już polecenie usuwania, prawda? To była tylko kwestia ścieżki, którą próbujesz usunąć, dzieląc się na znak spacji i usuwając znacznie więcej, niż się spodziewałem?
Christopher Shroba
18
... ale to, co „widzi się tutaj ”, jest zepsute. Oto poprawka:
Po prostu użyj echo $(cd ../ && pwd)podczas pracy w katalogu, którego katalog macierzysty chcesz znaleźć. Dodatkową zaletą tego łańcucha jest brak końcowych ukośników.
Używanie evalNIE jest świetne, jeśli istnieje szansa na przeanalizowanie danych wejściowych użytkownika, które mogą umieścić cię w miejscu, którego się nie spodziewasz, lub uruchomić złe rzeczy w systemie. Czy możesz użyć pushd $dir 2>&1 >/dev/null && pwd && popd 2>&1 >/dev/nullzamiast eval?
dragon788,
2
W ogóle nie potrzebujesz eval: po prostu rób parentdir=$(cd -- "$dir" && pwd). Ponieważ cdjest uruchamiany w podpowłoce, nie musisz cdwracać do miejsca, w którym byliśmy. --Jest tutaj w przypadku ekspansja $dirrozpoczyna się od myślnika. Chodzi &&tylko o to, aby nie parentdirmieć niepustej zawartości, gdy cdnie została zasysana.
gniourf_gniourf
8
Motywacja do kolejnej odpowiedzi
Lubię bardzo krótki, przejrzysty, gwarantowany kod. Punkt bonusowy, jeśli nie uruchomi zewnętrznego programu, ponieważ dzień, w którym musisz przetworzyć ogromną liczbę wpisów, będzie zauważalnie szybszy.
Zasada
Nie jestem pewien, jakie gwarancje masz i chcesz, więc i tak oferuj.
Jeśli masz gwarancje, możesz to zrobić za pomocą bardzo krótkiego kodu. Chodzi o to, aby użyć funkcji zastępowania tekstu bash, aby wyciąć ostatni ukośnik i wszystko, co następuje.
Odpowiedz od prostych do bardziej złożonych przypadków pierwotnego pytania.
Jeśli ścieżka kończy się bez żadnego ukośnika (wejście i wyjście)
Jeśli ścieżka wejściowa może kończyć się zero lub jednym ukośnikiem (nie więcej) i chcesz, aby ścieżka wyjściowa kończyła się bez ukośnika
for P in \
/home/smith/Desktop/Test \
/home/smith/Desktop/Test/do
P_ENDNOSLASH="${P%/}"; echo "${P_ENDNOSLASH%/*}"done/home/smith/Desktop/home/smith/Desktop
Jeśli ścieżka wejściowa może zawierać wiele obcych ukośników i chcesz, aby ścieżka wyjściowa kończyła się bez ukośnika
for P in \
/home/smith/Desktop/Test \
/home/smith/Desktop/Test/ \
/home/smith///Desktop////Test//do
P_NODUPSLASH="${P//\/*(\/)/\/}"
P_ENDNOSLASH="${P_NODUPSLASH%%/}"
echo "${P_ENDNOSLASH%/*}";done/home/smith/Desktop/home/smith/Desktop/home/smith/Desktop
Fantastyczna odpowiedź. Ponieważ wygląda na to, że szukał sposobu, aby to zrobić ze skryptu (znajdź bieżący katalog skryptu i jego obiekt nadrzędny i zrób coś w odniesieniu do miejsca, w którym skrypt się znajduje), jest to świetna odpowiedź i możesz mieć jeszcze większą kontrolę nad tym, czy wejście ma ukośnik końcowy lub nie poprzez użycie rozszerzenia parametru, w stosunku do ${BASH_SOURCE[0]}którego byłaby pełna ścieżka do skryptu, gdyby nie została uzyskana za pośrednictwem sourcelub ..
przepraszam, mam na myśli jak skrypt bash, mam zmienną ze ścieżką do pliku
YTKColumba
Uruchomienie tego kodu powoduje błąd bash: dirname 'Test': syntax error: invalid arithmetic operator (error token is "'Test'"). Połączony kod jest również niepoprawny.
Michael Hoffman,
spróbuj po prostu uruchomić dirname Testz katalogu Testjest w.
Jon Egeland
1
W zależności od tego, czy potrzebujesz ścieżek bezwzględnych, możesz zrobić dodatkowy krok:
local lookFor_ parent_ switch_ i_
lookFor_="$1"#if it is not a file, we need the grand parent[-f "$lookFor_"]|| switch_="/.."#length of search string
i_="${#lookFor_}"#remove string one by one until it make sens for the systemwhile["$i_"-ge 0]&&[!-d "${lookFor_:0:$i_}"];do
let i_--done#get real path
parent_="$(realpath "${lookFor_:0:$i_}$switch_")"#done
echo "
lookFor_: $1
{lookFor_:0:$i_}: ${lookFor_:0:$i_}
realpath {lookFor_:0:$i_}: $(realpath ${lookFor_:0:$i_})
parent_: $parent_
"
Jeśli z jakiegoś powodu jesteś zainteresowany poruszania się określony numer katalogów można także zrobić: nth_path=$(cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd ../../../ && pwd). Dałoby to 3 katalogi rodziców
..
”, ale być może nie o to ci chodziło.Odpowiedzi:
Działa, jeśli występuje również ukośnik końcowy.
źródło
parentdir=$(dirname `pwd`)
... ale to, co „widzi się tutaj ”, jest zepsute. Oto poprawka:
źródło
Po prostu użyj
echo $(cd ../ && pwd)
podczas pracy w katalogu, którego katalog macierzysty chcesz znaleźć. Dodatkową zaletą tego łańcucha jest brak końcowych ukośników.źródło
echo
tutaj.Oczywiście katalog nadrzędny jest podawany przez dodanie nazwy pliku kropka-kropka:
Ale musisz mieć rozstrzygniętą ścieżkę (ścieżka bezwzględna bez żadnych składników ścieżki kropka-kropka):
Problem z najczęściej używanymi odpowiedziami
dirname
polega na tym, że nie działają one po wprowadzeniu ścieżki z kropkami:Jest to bardziej wydajne :
Możesz go karmić
/home/smith/Desktop/Test/..
, ale także bardziej złożone ścieżki, takie jak:EDYCJA: Jeśli to nie działa, sprawdź, czy
cd
nie został zmodyfikowany, jak to często bywa,źródło
eval
NIE jest świetne, jeśli istnieje szansa na przeanalizowanie danych wejściowych użytkownika, które mogą umieścić cię w miejscu, którego się nie spodziewasz, lub uruchomić złe rzeczy w systemie. Czy możesz użyćpushd $dir 2>&1 >/dev/null && pwd && popd 2>&1 >/dev/null
zamiasteval
?eval
: po prostu róbparentdir=$(cd -- "$dir" && pwd)
. Ponieważcd
jest uruchamiany w podpowłoce, nie musiszcd
wracać do miejsca, w którym byliśmy.--
Jest tutaj w przypadku ekspansja$dir
rozpoczyna się od myślnika. Chodzi&&
tylko o to, aby nieparentdir
mieć niepustej zawartości, gdycd
nie została zasysana.Motywacja do kolejnej odpowiedzi
Lubię bardzo krótki, przejrzysty, gwarantowany kod. Punkt bonusowy, jeśli nie uruchomi zewnętrznego programu, ponieważ dzień, w którym musisz przetworzyć ogromną liczbę wpisów, będzie zauważalnie szybszy.
Zasada
Nie jestem pewien, jakie gwarancje masz i chcesz, więc i tak oferuj.
Jeśli masz gwarancje, możesz to zrobić za pomocą bardzo krótkiego kodu. Chodzi o to, aby użyć funkcji zastępowania tekstu bash, aby wyciąć ostatni ukośnik i wszystko, co następuje.
Odpowiedz od prostych do bardziej złożonych przypadków pierwotnego pytania.
Jeśli ścieżka kończy się bez żadnego ukośnika (wejście i wyjście)
Jeśli ścieżka kończy się dokładnie jednym ukośnikiem (wejście i wyjście)
Jeśli ścieżka wejściowa może kończyć się zero lub jednym ukośnikiem (nie więcej) i chcesz, aby ścieżka wyjściowa kończyła się bez ukośnika
Jeśli ścieżka wejściowa może zawierać wiele obcych ukośników i chcesz, aby ścieżka wyjściowa kończyła się bez ukośnika
źródło
${BASH_SOURCE[0]}
którego byłaby pełna ścieżka do skryptu, gdyby nie została uzyskana za pośrednictwemsource
lub.
.Jeśli
/home/smith/Desktop/Test/../
tego chcesz:jak widać tutaj .
źródło
bash: dirname 'Test': syntax error: invalid arithmetic operator (error token is "'Test'")
. Połączony kod jest również niepoprawny.dirname Test
z kataloguTest
jest w.W zależności od tego, czy potrzebujesz ścieżek bezwzględnych, możesz zrobić dodatkowy krok:
źródło
Użyj tego :
export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")"
jeśli chcesz 4. katalog nadrzędnyexport MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")"
jeśli chcesz trzeci katalog nadrzędnyexport MYVAR="$(dirname "$(dirname $PWD)")"
jeśli chcesz drugi katalog nadrzędnyźródło
brzydki, ale wydajny
{
}
źródło
Zaczął od pomysłu / komentarza Charles Duffy - 17 grudnia 14 'o 5:32 na temat Uzyskaj nazwę bieżącego katalogu (bez pełnej ścieżki) w skrypcie Bash
źródło
Jeśli z jakiegoś powodu jesteś zainteresowany poruszania się określony numer katalogów można także zrobić:
nth_path=$(cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd ../../../ && pwd)
. Dałoby to 3 katalogi rodzicówźródło