Jakiej komendy można użyć do sprawdzenia, czy katalog istnieje w skrypcie powłoki Bash?
3719
Aby sprawdzić, czy katalog istnieje w skrypcie powłoki, możesz użyć następujących poleceń:
if [ -d "$DIRECTORY" ]; then
# Control will enter here if $DIRECTORY exists.
fi
Lub sprawdzić, czy katalog nie istnieje:
if [ ! -d "$DIRECTORY" ]; then
# Control will enter here if $DIRECTORY doesn't exist.
fi
Jednak, jak zauważa Jon Ericson , kolejne polecenia mogą nie działać zgodnie z przeznaczeniem, jeśli nie weźmie się pod uwagę, że dowiązanie symboliczne do katalogu również przejdzie tę kontrolę. Np. Uruchomienie tego:
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
Dlatego dowiązania symboliczne mogą wymagać innego traktowania, 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. Przyczynę tego wyjaśnia 8jean w innej odpowiedzi .
Jeśli zmienne zawierają spacje lub inne nietypowe znaki, prawdopodobnie spowoduje to awarię skryptu.
--
wysoce zalecane jest użycie (znacznika końca opcji). W przeciwnym razie, jeśli twoja zmienna zawiera coś, co wygląda jak opcja, skrypt zawiedzie tak samo jak spacje.[ ! -d "$DIRECTORY" ]
będzie prawdziwa albo jeśli$DIRECTORY
nie istnieje, czy nie istnieje, ale nie jest katalogiem. Zastanów się nad czymś takimif [ ! -d "$DIRECTORY" ] ; then mkdir "$DIRECTORY" ; fi
; to się nie powiedzie, jeśli"$DIRECTORY"
jest to plik. (Oczywiście powinieneś sprawdzić, czy imkdir
tak się udało; istnieje wiele powodów, dla których może się nie powieść).-d
), jak i dowiązania symbolicznego (-L
), łatwiej jest po prostu dodać ukośnik do zmiennej, npif [ -d "${THING:+$THING/}" ]
. Katalog nie będzie miał nic przeciwko dodatkowemu ukośnikowi. Plik zostanie oceniony jako fałszywy. Puste pozostanie puste, więc fałszywe. I dowiązanie symboliczne zostanie rozstrzygnięte do miejsca docelowego. Oczywiście zależy to od twojego celu. Jeśli chcesz się tam wybrać, nie ma sprawy. Jeśli chcesz go usunąć , kod w tej odpowiedzi jest lepszy.Pamiętaj, aby zawsze umieszczać zmienne w podwójnych cudzysłowach, odwołując się do nich w skrypcie Bash. W dzisiejszych czasach dzieci dorastają z myślą, że w nazwach katalogów mogą mieć spacje i wiele innych zabawnych postaci. (Przestrzenie! Za moich czasów nie mieliśmy żadnych wymyślnych miejsc!;))
Pewnego dnia jedno z tych dzieci uruchomi twój skrypt z
$DIRECTORY
ustawionym na"My M0viez"
i twój skrypt wybuchnie. Nie chcesz tego Więc skorzystaj z tego.źródło
Zauważ, że test -d może dać zaskakujące wyniki:
Plik poniżej: „Kiedy katalog nie jest katalogiem?” Odpowiedź: „Gdy jest to dowiązanie symboliczne do katalogu”. Nieco dokładniejszy test:
Więcej informacji można znaleźć w podręczniku Bash na temat wyrażeń warunkowych Bash oraz
[
wbudowanego polecenia i polecenia[[
złożonego .źródło
if [ -d tmpdir -a ! -L tmpdir ]; then echo "is directory"; rmdir tmpdir; fi
... lub, dla jednego polecenia, które działa na obu linkach i katalogach:rm -r tmpdir
Uważam, że wersja z podwójnymi nawiasami
test
sprawia, że pisanie testów logicznych jest bardziej naturalne:źródło
if [[ -d "$TARFILE" ]]
Dostaję [[: Nie znaleziono[[ ]]
jest obsługiwany z domyślnymi opcjami kompilacji , ale w rzeczywistości nie zapewnia żadnych innych funkcji[ ]
. Jeśli problemem jest przenośność, trzymaj[ ]
się koniecznych obejść i korzystaj z nich.Krótsza forma:
źródło
if $dir is a dir, then echo "yes"
:? Trochę wyjaśnienia pomogłoby :)cmd && other
jest częstym skrótemif cmd; then other; fi
- działa z większością języków programowania obsługujących logikę boolowską i jest znany jako ocena zwarcia .set -e
(co jest najlepszą praktyką programowania powłoki ).[ -d "$DIR" ]
jest zaznaczone (po którym następuje&& echo Yes
), więc uważam,set -e
że nie ma znaczenia dla zachowania skryptu (tj. jeśli test się nie powiedzie, skrypt będzie kontynuował normalnie).Aby sprawdzić, czy katalog istnieje, możesz użyć prostej
if
struktury takiej jak ta:Możesz to również zrobić negatywnie:
Uwaga : bądź ostrożny. Pozostaw puste miejsca po obu stronach nawiasów otwierających i zamykających.
Przy tej samej składni możesz użyć:
źródło
Prosty skrypt do sprawdzenia, czy katalog lub plik jest obecny, czy nie:
Prosty skrypt, aby sprawdzić, czy katalog jest obecny, czy nie:
Powyższe skrypty sprawdzą, czy katalog jest obecny, czy nie
$?
jeśli ostatnie polecenie zakończy się powodzeniem, zwraca „0”, w przeciwnym razie wartość niezerowa. Załóżmy, żetempdir
jest już obecny. Następniemkdir tempdir
wyświetli błąd jak poniżej:źródło
Możesz użyć
test -d
(patrzman test
).Na przykład:
Uwaga:
test
polecenie jest takie samo jak wyrażenie warunkowe[
(patrzman [
:), więc jest przenośne w skryptach powłoki.Aby uzyskać dostępne opcje lub dalszą pomoc, sprawdź:
help [
help test
man test
lubman [
źródło
Lub coś zupełnie bezużytecznego:
źródło
Oto bardzo pragmatyczny idiom:
Zazwyczaj pakuję go w funkcję:
Lub:
Zaletą tego podejścia jest to, że nie muszę myśleć o dobrym komunikacie o błędzie.
cd
wyśle mi już standardowy komunikat w jednym wierszu do standardowego błędu . Poda także więcej informacji, niż będę w stanie podać. Wykonująccd
wewnątrz podpowłoki( ... )
, polecenie nie wpływa na bieżący katalog dzwoniącego. Jeśli katalog istnieje, ta podpowłoka i funkcja są po prostu niedostępne.Dalej jest argument, że możemy przejść do
cd
:${1:?pathname expected}
. Jest to bardziej skomplikowana forma podstawiania parametrów, którą wyjaśniono bardziej szczegółowo poniżej.Tl; dr: Jeśli ciąg przekazany do tej funkcji jest pusty, ponownie wychodzimy z podpowłoki
( ... )
i wracamy z funkcji z podanym komunikatem o błędzie.Cytowanie ze strony
ksh93
man:i
Frazowanie tutaj jest specyficzne dla dokumentacji powłoki, ponieważ
word
może odnosić się do dowolnego rozsądnego ciągu, 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 powiększam typ oczekiwanej tutajpathname
wartości - katalogu.Nota filozoficzna:
Powłoka nie jest językiem zorientowanym obiektowo, więc komunikat mówi
pathname
, że niedirectory
. Na tym poziomie wolę to uprościć - argumenty funkcji są tylko ciągami znaków.źródło
test -d
taka, jak wyjaśniono @Grundlefleck.test -d /unreadable/exists
zawiedzie, nawet jeśli argument istnieje.Powyższy kod sprawdza, czy katalog istnieje i czy można go zapisać.
źródło
Wypróbuj online
źródło
space
po[
-> [`` -d . dostałem błąd z powodu braku miejscaWpisz ten kod w wierszu polecenia Bash:
źródło
Więcej funkcji za pomocą
find
Sprawdź istnienie folderu w podkatalogach:
Sprawdź istnienie jednego lub kilku folderów na podstawie wzorca w bieżącym katalogu:
Obie kombinacje. W poniższym przykładzie sprawdza istnienie folderu w bieżącym katalogu:
źródło
find -maxdepth 1 -type d -name 'pattern'
. Czy masz coś przeciwko, jeśli w odpowiedzi dodam tę sztuczkę? Pozdrawiam;)Właściwie powinieneś użyć kilku narzędzi, aby uzyskać kuloodporne podejście:
Tak długo, jak używasz, nie musisz się martwić spacjami i znakami specjalnymi
"${}"
.Zauważ, że
[[]]
nie jest tak przenośny jak[]
, ale ponieważ większość ludzi pracuje z nowoczesnymi wersjami Bash (ponieważ w końcu większość ludzi nawet nie pracuje z wierszem poleceń :-p), korzyść jest większa niż kłopot.źródło
Czy zastanawiałeś się nad zrobieniem tego, co chcesz,
if
zamiast patrzeć przed skokiem?To znaczy, jeśli chcesz sprawdzić istnienie katalogu przed jego wprowadzeniem, spróbuj zrobić to:
Jeśli ścieżka, którą podajesz,
pushd
istnieje, wprowadzisz ją i zakończysz za pomocą0
, co oznacza, żethen
część instrukcji zostanie wykonana. Jeśli nie istnieje, nic się nie wydarzy (oprócz niektórych danych wyjściowych, że katalog nie istnieje, co jest prawdopodobnie pomocnym efektem ubocznym przy debugowaniu).Wydaje się to lepsze niż to, co wymaga powtórzenia się:
To samo działa z
cd
,mv
,rm
, etc ... jeśli spróbujesz je na pliki, które nie istnieją, będą mogły wyjść z błędu i wydrukować wiadomość, mówiąc, że nie istnieje, athen
blok zostanie pominięty. Jeśli wypróbujesz je na istniejących plikach, polecenie zostanie wykonane i zakończy się ze statusem0
, umożliwiającthen
wykonanie bloku.źródło
Aby sprawdzić więcej niż jeden katalog, użyj tego kodu:
źródło
Sprawdź, czy katalog istnieje, w przeciwnym razie utwórz go:
źródło
mkdir -p "$DIRECTORY"
tego samego efektu.Wyjaśnienie:
-d
: sprawdź, czy to katalog-L
: sprawdź, czy jest to link symbolicznyźródło
źródło
Ta odpowiedź jest zapakowana jako skrypt powłoki
Przykłady
is_dir
źródło
Użycie tej opcji
-e
sprawdzi, czy są dostępne pliki, w tym katalogi.źródło
Zgodnie z komentarzem Jonathana :
Jeśli chcesz utworzyć katalog, który jeszcze nie istnieje, to najprostszą techniką jest użycie tego,
mkdir -p
który tworzy katalog - i wszelkie brakujące katalogi na ścieżce - i nie zawiedzie, jeśli katalog już istnieje, więc możesz zrobić to wszystko od razu z:źródło
To nie do końca prawda ...
Jeśli chcesz przejść do tego katalogu, musisz także mieć uprawnienia do wykonywania tego katalogu. Być może musisz również mieć prawa do zapisu.
W związku z tym:
źródło
Skorzystaj z
file
programu. Biorąc pod uwagę, że wszystkie katalogi są również plikami w systemie Linux, wystarczyłoby wykonać następujące polecenie:file $directory_name
Sprawdzanie nieistniejącego pliku:
file blah
Wynik:
cannot open 'blah' (No such file or directory)
Sprawdzanie istniejącego katalogu:
file bluh
Wynik:
bluh: directory
źródło
ls
Polecenia w połączeniu z-l
(długie liście) deklaracji atrybutów opcjonalnych informacji o plikach i katalogach.W szczególności pierwszym znakiem
ls -l
wyjścia jest zwykle ad
lub-
myślnik. W przypadkud
jednego z wymienionych jest na pewno katalog.Poniższe polecenie w jednym wierszu powie ci, czy dana
ISDIR
zmienna zawiera ścieżkę do katalogu, czy nie:Praktyczne zastosowanie:
źródło
źródło
Jeśli chcesz sprawdzić, czy katalog istnieje, niezależnie od tego, czy jest to prawdziwy katalog, czy dowiązanie symboliczne, użyj tego:
Objaśnienie: Komenda „ls” wyświetla błąd „ls: / x: Brak takiego pliku lub katalogu”, jeśli katalog lub dowiązanie symboliczne nie istnieje, a także ustawia kod powrotu, który można pobrać za pomocą „$?”, Na wartość inną niż -null (zwykle „1”). Pamiętaj, aby sprawdzić kod powrotu bezpośrednio po wywołaniu „ls”.
źródło
if ! ls $DIR 2>/dev/null; then echo "$DIR does not exist!"; fi
(1)
(2)
(3)
Jeśli zostanie znaleziony problem z jednym z powyższych sposobów:
Z
ls
rozkazem; przypadki, gdy katalog nie istnieje - wyświetlany jest komunikat o błędzieźródło
Istnieją świetne rozwiązania, ale ostatecznie każdy skrypt zawiedzie, jeśli nie znajdziesz się w odpowiednim katalogu. Więc kod taki:
wykona się pomyślnie tylko wtedy, gdy w chwili wykonania znajdujesz się w katalogu z podkatalogiem, którego szukasz.
Rozumiem początkowe pytanie w ten sposób: aby sprawdzić, czy katalog istnieje niezależnie od pozycji użytkownika w systemie plików. Zatem użycie polecenia „znajdź” może załatwić sprawę:
To rozwiązanie jest dobre, ponieważ pozwala na użycie symboli wieloznacznych, użytecznej funkcji podczas wyszukiwania plików / katalogów. Jedyny problem polega na tym, że jeśli przeszukiwany katalog nie istnieje, polecenie „znajdź” nie wypisuje nic na standardowe wyjście (nie jest to eleganckie rozwiązanie według mojego gustu) i mimo to ma zerowe wyjście. Może ktoś mógłby to poprawić.
źródło
locate
ale nie dla niczego innego ...