Pytanie Sprawdź, czy istnieje katalog w skrypcie powłoki


Jakiej komendy można użyć do sprawdzenia, czy katalog istnieje, czy nie, w skrypcie powłoki?


2999
2017-09-12 20:06


pochodzenie




Odpowiedzi:


Aby sprawdzić, czy katalog istnieje w skrypcie powłoki, możesz użyć:

if [ -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY exists.
fi

Lub, aby sprawdzić, czy katalog nie istnieje:

if [ ! -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY doesn't exist.
fi

Jednak jako Jon Ericson zwraca uwagę, że kolejne polecenia mogą nie działać zgodnie z przeznaczeniem, jeśli nie bierzesz pod uwagę, że dowiązanie symboliczne do katalogu również przejdzie tę kontrolę. Na przykład. uruchamiając to:

ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then 
  rmdir "$SYMLINK" 
fi

Wyświetli komunikat o błędzie:

rmdir: failed to remove `symlink': Not a directory

Więc linki symboliczne mogą być traktowane inaczej, jeśli kolejne polecenia oczekują katalogów:

if [ -d "$LINK_OR_DIR" ]; then 
  if [ -L "$LINK_OR_DIR" ]; then
    # It is a symlink!
    # Symbolic link specific commands go here.
    rm "$LINK_OR_DIR"
  else
    # It's a directory!
    # Directory command goes here.
    rmdir "$LINK_OR_DIR"
  fi
fi

Zwróć szczególną uwagę na podwójne cudzysłowy używane do zawijania zmiennych, a przyczyna tego jest wyjaśniona przez 8jean w innej odpowiedzi.

Jeśli zmienne zawierają spacje lub inne nietypowe znaki, prawdopodobnie spowoduje to niepowodzenie skryptu.


4144
2017-09-12 20:07



Jeśli chcesz grać bezpiecznie używając narzędzi GNU, użyj -- jest wysoce zalecany (znacznik końca opcji). W przeciwnym razie, jeśli zmienna zawiera coś, co wygląda jak opcja, skrypt zakończy się niepowodzeniem, podobnie jak w przypadku spacji. - Marc Mutz - mmutz
Dla współczesnych wersji basha, ksh itp. [...] jest wbudowany - fpmurphy1
Jedna rzecz, o której należy pamiętać: [ ! -d "$DIRECTORY" ] będzie prawdą, jeśli $DIRECTORY nie istnieje lub jeśli robi istnieje, ale nie jest katalogiem. Rozważ coś takiego if [ ! -d "$DIRECTORY" ] ; then mkdir "$DIRECTORY" ; fi; to się nie powiedzie, jeśli "$DIRECTORY" jest plikiem. (Oczywiście powinieneś sprawdzić, czy mkdir udało się i tak; jest wiele powodów, dla których może się to nie udać.) - Keith Thompson
Warto wspomnieć, że jak tylko kontrola została wykonana, sytuacja mogła się już zmienić z powodu innych procesów. W wielu przypadkach lepiej jest po prostu stworzyć lub używać katalogu i reagować na awarię. - Alfe
Zamiast testowania dla obu katalogów (-d) i dowiązanie symboliczne (-L), łatwiej jest dopisać ukośnik do zmiennej, np. if [ -d "${THING:+$THING/}" ]. Katalog nie będzie miał nic przeciwko dodatkowemu ukośnikowi. Plik oceni na false. Pusty pozostanie pusty, tak fałszywy. I dowiązanie symboliczne zostanie rozwiązane do miejsca przeznaczenia. Oczywiście zależy to od celu. Jeśli chcesz udać się tam jest w porządku. Jeśli chcesz Usuń to, kod w tej odpowiedzi jest lepszy. - ghoti


Pamiętaj, aby zawsze zawijać zmienne w podwójnych cudzysłowach podczas ich przywoływania skrypt bash. W dzisiejszych czasach dzieci dorastają z myślą, że w nazwach katalogów mogą znajdować się spacje i wiele innych zabawnych postaci. (Przestrzenie, w moich czasach, nie mieliśmy żadnych wymyślnych przestrzeni!)))

Pewnego dnia jedno z tych dzieci poprowadzi twój scenariusz $DIRECTORY Ustawić "My M0viez" a twój scenariusz wybuchnie. Nie chcesz tego. Więc użyj tego.

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists, even if it contains spaces
fi

454
2017-09-15 22:00



Innym powodem używania podwójnych cudzysłowów jest sytuacja, gdy $ DIRECTORY nie jest ustawione z jakiegoś powodu. - Jon Ericson♦
"zawsze zawijaj zmienne w podwójny cudzysłów ... w skrypcie basha." W przypadku basha nie jest to technicznie konieczne, gdy używa się [[...]]; widzieć tldp.org/LDP/abs/html/testconstructs.html#DBLBRACKETS (uwaga: brak dzielenia wyrazów): "Żadne rozszerzenie nazwy pliku lub podział słów nie ma miejsca między [[i]], ale istnieje rozszerzenie parametrów i podstawienie poleceń." - michael
Katalogi w systemie Unix / Linux nie powinny mieć żadnych białych znaków, a następnie skrypty nie powinny być do niego dostosowywane. Szkoda, że ​​Windows go obsługuje, co ma wpływ na skrypty Windows, ale proszę, z miłości do czegokolwiek, bez potrzeby wprowadzania niepotrzebnych wymagań. - tvCa
@tvCa Uważam, że użytkownicy na ogół wolą mieć większą elastyczność w nazwach swoich katalogów niż być zmuszonym do ułatwiania programistom. (W rzeczywistości, gdy mam do czynienia z długimi nazwami plików, uważam, że bez spacji nie jest to ból, ponieważ zabija to zawijanie słów, mimo że ja sam cierpiałem w przeszłości, nie uwzględniając ścieżek zawierających spacje w skryptach i programach). - JAB
Ha. Spacje to po prostu znaki, które zwykle nie mają żadnych glifów. W każdym razie możesz uciec z nich za pomocą odwrotnego ukośnika. - uchuugaka


Zanotuj -re test może dać zaskakujące wyniki:

$ ln -s tmp/ t
$ if [ -d t ]; then rmdir t; fi
rmdir: directory "t": Path component not a directory

Plik pod: "Kiedy katalog nie jest katalogiem?" Odpowiedź: "Gdy jest to dowiązanie symboliczne do katalogu". Nieco dokładniejszy test:

if [ -d t ]; then 
   if [ -L t ]; then 
      rm t
   else 
      rmdir t
   fi
fi

Więcej informacji znajdziesz w instrukcji Bash Wyrażenia warunkowe bash i [ wbudowane polecenie i [[ złożony komunikat.


204
2017-09-12 20:26



lub, zakładając, że jest to konieczne tylko do pracy na katalogach (i linki mogą być ignorowane) => if [ -d tmpdir -a ! -L tmpdir ]; then echo "is directory"; rmdir tmpdir; fi ... lub, dla jednego polecenia działającego na obu linkach i katalogach: rm -r tmpdir - michael


Znajduję podwójny wspornik wersja test sprawia, że ​​pisanie testów logicznych jest bardziej naturalne:

if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
    echo "It's a bona-fide directory"
fi

198
2017-09-12 21:33



dla if [[ -d "$TARFILE" ]] Otrzymuję [[: not found - TheVillageIdiot
ditto [[: not found - Hedgehog
@TheVillageIdiot i @Hedgehog, używasz powłoki bash? Podwójny uchwyt nie jest powszechnie obsługiwany. Oto odpowiedź na to pytanie: stackoverflow.com/questions/669452/... - yukondude
A w Busybox popiołu z domyślnymi opcjami kompilacji [[ ]] jest obsługiwany, ale w rzeczywistości nie zapewnia żadnej innej funkcji [ ]. Jeśli przenośność jest problemem, trzymaj się [ ] i użyj niezbędnych obejść. - dubiousjim
... jeśli używasz konstruktów bash w skrypcie powłoki, pierwsza linia skryptu powinna być: #! / bin / bash (a nie #! / bin / sh, ksh, itp) - michael


Krótsza forma:

[ -d "$DIR" ] && echo "Yes"

125
2017-09-12 21:08



Czy to działa tak: if $dir is a dir, then echo "yes"? Trochę wyjaśnienia pomogłoby :) - Martijn
cmd && other jest wspólnym skrótem dla if cmd; then other; fi - działa z większością języków programowania, które obsługują logikę Boolean i jest znany jako ocena zwarcia. - tripleee
To zachowanie nie jest takie samo set -e (który jest najlepsze praktyki programowania powłoki). - dolmen


Aby sprawdzić, czy istnieje katalog, możesz użyć prostej, jeśli taka struktura wygląda następująco:

if [ -d directory/path to a directory ] ; then
#Things to do

else #if needed #also: elif [new condition] 
# things to do
fi

Możesz to zrobić również w negatywie

if [ ! -d directory/path to a directory ] ; then
# things to do when not an existing directory

Uwaga: Zachowaj ostrożność, pozostaw puste przestrzenie po obu stronach obu klamr otwierających i zamykających.

Dzięki tej samej składni możesz użyć:

-e: any kind of archive 

-f: file 

-h: symbolic link 

-r: readable file 

-w: writable file 

-x: executable file 

-s: file size greater than zero 

119
2018-04-08 02:50





if [ -d "$DIRECTORY" ]; then  
    # Here if $DIRECTORY exists  
fi

94
2018-04-15 08:07





Możesz użyć test -d (widzieć man test).

-d file       Prawda, jeśli plik istnieje i jest katalogiem.

Na przykład:

test -d "/etc" && echo Exists || echo Does not exist

Zanotuj test polecenie jest takie samo jak wyrażenie warunkowe [ (widzieć: man [), więc jest przenośny w skryptach powłoki.

[ - To jest synonim test wbudowany, ale ostatni argument musi być dosłowny ], aby dopasować się do otwarcia [.

Aby uzyskać opcje lub dalszą pomoc, sprawdź:

  • help [
  • help test
  • man test lub man [

74
2017-09-12 21:25





Albo coś zupełnie bezużytecznego:

[ -d . ] || echo "No"

55
2017-08-17 14:02



Nigdy nie wydrukuje "Nie". Aktualny katalog zawsze istnieje, o ile nie zostanie usunięty przez inny wątek lub inne sposoby. - Jahid
Doskonała próbka :) biorąc pod uwagę, że "unikatowe" są niektóre odpowiedzi w porównaniu do zaakceptowanej odpowiedzi - Sergey Sargsyan
Dlaczego tak wiele razy zostało przegłosowane? Nie odpowiada na pytanie. - codeforester


Oto bardzo pragmatyczny idiom:

(cd $dir) || return # is this a directory,
                    # and do we have access?

Zazwyczaj zawijam ją w funkcję:

can_use_as_dir() { 
    (cd ${1:?pathname expected}) || return
}

Lub:

assert_dir_access() { 
    (cd ${1:?pathname expected}) || exit
}

Zaletą tego podejścia jest to, że nie muszę myśleć o dobrym komunikacie o błędzie.

cd da mi standardową, jednoliniową wiadomość do stderr już. Da także więcej informacji, niż będę w stanie zapewnić. Wykonując cd wewnątrz podpowłoki ( ... ), polecenie nie wpływa na bieżący katalog osoby dzwoniącej. Jeśli katalog istnieje, to podpowłodzenie i funkcja są po prostu nieopierzone.

Następny argument, do którego przechodzimy cd: ${1:?pathname expected}. Jest to bardziej rozbudowana forma zastępowania parametrów, która zostanie wyjaśniona bardziej szczegółowo poniżej.

Tl; dr: Jeśli ciąg znaków przekazany do tej funkcji jest pusty, ponownie wychodzimy z podpowłoki ( ... ) i powrócić z funkcji z podanym komunikatem o błędzie.


Cytując z ksh93 strona man:

${parameter:?word}

Gdyby parameter  jest ustawiony i ma wartość inną niż null, a następnie zastępuje jego wartość;   w przeciwnym razie wydrukuj word i wyjść z powłoki (jeśli nie jest interaktywna).   Gdyby word jest pomijany, a następnie drukowany jest standardowy komunikat.

i

Jeśli dwukropek : jest pominięte w powyższych wyrażeniach, a następnie   powłoka sprawdza tylko, czy parametr jest ustawiony, czy nie.

Frazowanie tutaj jest specyficzne dla dokumentacji powłoki, jako word może odnosić się do dowolnego rozsądnego ciągu znaków, w tym białych znaków.

W tym konkretnym przypadku wiem, że standardowy komunikat o błędzie 1: parameter not set nie jest wystarczający, więc przybliżam rodzaj wartości, który tutaj spodziewamy - pathname katalogu.

Notatka filozoficzna: Powłoka nie jest językiem zorientowanym na obiekt, więc komunikat mówi pathname, nie directory. Na tym poziomie wolałbym zachować prostotę - argumenty funkcji są po prostu ciągami.


46
2017-08-09 21:43



To robi więcej niż tylko sprawdzanie, czy istnieje: To sprawdzenie dostępności na poziomie użytkownika. CZYM pytanie dotyczy istnienie tylko. Tak więc właściwa odpowiedź test -d jak @Grundlefleck wyjaśnił. - F. Hauri
@ F.Hauri - Nie prosił o nic więcej, to prawda. Jednak odkryłem, że zazwyczaj muszę wiedzieć więcej. - Henk Langeveld
I nigdy nie przyszło mi do głowy, że żaden test nie może być rozstrzygający, chyba że działa jako root. test -d /unreadable/exists zawiedzie, nawet jeśli argument będzie istnieć. - Henk Langeveld


if [ -d "$Directory" -a -w "$Directory" ]
then
    #Statements
fi

Powyższy kod sprawdza, czy katalog istnieje i czy jest zapisywalny.


35
2018-04-21 06:06



-a jest identyczne w stosunku do -e. Został "przestarzały", a jego użycie jest odradzane. - CousinCocaine