Jakiej komendy można użyć do sprawdzenia, czy katalog istnieje w skrypcie powłoki Bash?
Jakiej komendy można użyć do sprawdzenia, czy katalog istnieje w skrypcie powłoki Bash?
Odpowiedzi:
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.
[ ! -d "$DIRECTORY" ]
będzie prawdziwa albo jeśli $DIRECTORY
nie istnieje, czy nie istnieje, ale nie jest katalogiem. Zastanów się nad czymś takim if [ ! -d "$DIRECTORY" ] ; then mkdir "$DIRECTORY" ; fi
; to się nie powiedzie, jeśli "$DIRECTORY"
jest to plik. (Oczywiście powinieneś sprawdzić, czy i mkdir
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, np if [ -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.
if [ -d "$DIRECTORY" ]; then
# Will enter here if $DIRECTORY exists, even if it contains spaces
fi
Zauważ, że test -d 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 poniżej: „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 można znaleźć w podręczniku Bash na temat wyrażeń warunkowych Bash oraz [
wbudowanego polecenia i polecenia [[
złożonego .
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 nawiasamitest
sprawia, że pisanie testów logicznych jest bardziej naturalne:
if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
echo "It's a bona-fide directory"
fi
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:
[ -d "$DIR" ] && echo "Yes"
if $dir is a dir, then echo "yes"
:? Trochę wyjaśnienia pomogłoby :)
cmd && other
jest częstym skrótem if 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:
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 również zrobić negatywnie:
if [ ! -d directory/path to a directory ] ; then
# Things to do when not an existing directory
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ć:
-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
Prosty skrypt do sprawdzenia, czy katalog lub plik jest obecny, czy nie:
if [ -d /home/ram/dir ] # For file "if [-f /home/rama/file]"
then
echo "dir present"
else
echo "dir not present"
fi
Prosty skrypt, aby sprawdzić, czy katalog jest obecny, czy nie:
mkdir tempdir # If you want to check file use touch instead of mkdir
ret=$?
if [ "$ret" == "0" ]
then
echo "dir present"
else
echo "dir not present"
fi
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, że tempdir
jest już obecny. Następnie mkdir tempdir
wyświetli błąd jak poniżej:
mkdir: nie można utworzyć katalogu „tempdir”: plik istnieje
Możesz użyć test -d
(patrz man test
).
-d file
Prawda, jeśli plik istnieje i jest katalogiem.
Na przykład:
test -d "/etc" && echo Exists || echo Does not exist
Uwaga: test
polecenie jest takie samo jak wyrażenie warunkowe [
(patrz man [
:), więc jest przenośne w skryptach powłoki.
[
- To jest synonimtest
wbudowanego, ale ostatni argument musi być dosłowny]
, aby pasował do otwarcia[
.
Aby uzyskać dostępne opcje lub dalszą pomoc, sprawdź:
help [
help test
man test
lub man [
Lub coś zupełnie bezużytecznego:
[ -d . ] || echo "No"
Oto bardzo pragmatyczny idiom:
(cd $dir) || return # Is this a directory,
# and do we have access?
Zazwyczaj pakuję go 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
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ąc cd
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:
${parameter:?word}
Jeśli
parameter
jest ustawiony i jest różny od zera, wówczas podstaw jego wartość; w przeciwnym razie wydrukujword
i wyjdź z powłoki (jeśli nie jest interaktywny). Jeśliword
zostanie pominięty, zostanie wydrukowany standardowy komunikat.
i
Jeśli dwukropek
:
zostanie pominięty w powyższych wyrażeniach, wówczas powłoka sprawdza tylko, czy parametr jest ustawiony czy nie.
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 tutaj pathname
wartości - katalogu.
Nota filozoficzna:
Powłoka nie jest językiem zorientowanym obiektowo, więc komunikat mówi pathname
, że nie directory
. Na tym poziomie wolę to uprościć - argumenty funkcji są tylko ciągami znaków.
test -d
taka, jak wyjaśniono @Grundlefleck.
test -d /unreadable/exists
zawiedzie, nawet jeśli argument istnieje.
if [ -d "$Directory" -a -w "$Directory" ]
then
#Statements
fi
Powyższy kod sprawdza, czy katalog istnieje i czy można go zapisać.
DIRECTORY=/tmp
if [ -d "$DIRECTORY" ]; then
echo "Exists"
fi
space
po [
-> [`` -d . dostałem błąd z powodu braku miejsca
Wpisz ten kod w wierszu polecenia Bash:
if [ -d "$DIRECTORY" ]; then
# If true this block of code will execute
fi
find
Sprawdź istnienie folderu w podkatalogach:
found=`find -type d -name "myDirectory"`
if [ -n "$found"]
then
# The variable 'found' contains the full path where "myDirectory" is.
# It may contain several lines if there are several folders named "myDirectory".
fi
Sprawdź istnienie jednego lub kilku folderów na podstawie wzorca w bieżącym katalogu:
found=`find -maxdepth 1 -type d -name "my*"`
if [ -n "$found"]
then
# The variable 'found' contains the full path where folders "my*" have been found.
fi
Obie kombinacje. W poniższym przykładzie sprawdza istnienie folderu w bieżącym katalogu:
found=`find -maxdepth 1 -type d -name "myDirectory"`
if [ -n "$found"]
then
# The variable 'found' is not empty => "myDirectory"` exists.
fi
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:
DIR_PATH=`readlink -f "${the_stuff_you_test}"` # Get rid of symlinks and get abs path
if [[ -d "${DIR_PATH}" ]] ; Then # Now you're testing
echo "It's a dir";
fi
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.
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:
if pushd /path/you/want/to/enter; then
# Commands you want to run in this directory
popd
fi
Jeśli ścieżka, którą podajesz, pushd
istnieje, wprowadzisz ją i zakończysz za pomocą 0
, co oznacza, że then
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ę:
if [ -d /path/you/want/to/enter ]; then
pushd /path/you/want/to/enter
# Commands you want to run in this directory
popd
fi
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, a then
blok zostanie pominięty. Jeśli wypróbujesz je na istniejących plikach, polecenie zostanie wykonane i zakończy się ze statusem 0
, umożliwiając then
wykonanie bloku.
Aby sprawdzić więcej niż jeden katalog, użyj tego kodu:
if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
# Things to do
fi
Sprawdź, czy katalog istnieje, w przeciwnym razie utwórz go:
[ -d "$DIRECTORY" ] || mkdir $DIRECTORY
mkdir -p "$DIRECTORY"
tego samego efektu.
[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"
NB: Cytowanie zmiennych jest dobrą praktyką.
Wyjaśnienie:
-d
: sprawdź, czy to katalog-L
: sprawdź, czy jest to link symboliczny[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"
Ta odpowiedź jest zapakowana jako skrypt powłoki
$ is_dir ~
YES
$ is_dir /tmp
YES
$ is_dir ~/bin
YES
$ mkdir '/tmp/test me'
$ is_dir '/tmp/test me'
YES
$ is_dir /asdf/asdf
NO
# Example of calling it in another script
DIR=~/mydata
if [ $(is_dir $DIR) == "NO" ]
then
echo "Folder doesnt exist: $DIR";
exit;
fi
function show_help()
{
IT=$(CAT <<EOF
usage: DIR
output: YES or NO, depending on whether or not the directory exists.
)
echo "$IT"
exit
}
if [ "$1" == "help" ]
then
show_help
fi
if [ -z "$1" ]
then
show_help
fi
DIR=$1
if [ -d $DIR ]; then
echo "YES";
exit;
fi
echo "NO";
Użycie tej opcji -e
sprawdzi, czy są dostępne pliki, w tym katalogi.
if [ -e ${FILE_PATH_AND_NAME} ]
then
echo "The file or directory exists."
fi
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:
mkdir -p /some/directory/you/want/to/exist || exit 1
if [ -d "$DIRECTORY" ]; then
# Will enter here if $DIRECTORY exists
fi
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:
if [ -d "$DIRECTORY" ] && [ -x "$DIRECTORY" ] ; then
# ... to go to that directory (even if DIRECTORY is a link)
cd $DIRECTORY
pwd
fi
if [ -d "$DIRECTORY" ] && [ -w "$DIRECTORY" ] ; then
# ... to go to that directory and write something there (even if DIRECTORY is a link)
cd $DIRECTORY
touch foobar
fi
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
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 a d
lub -
myślnik. W przypadku d
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:
[[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
echo "YES, $ISDIR is a directory." ||
echo "Sorry, $ISDIR is not a directory"
Praktyczne zastosowanie:
[claudio@nowhere ~]$ ISDIR="$HOME/Music"
[claudio@nowhere ~]$ ls -ld "$ISDIR"
drwxr-xr-x. 2 claudio claudio 4096 Aug 23 00:02 /home/claudio/Music
[claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
echo "YES, $ISDIR is a directory." ||
echo "Sorry, $ISDIR is not a directory"
YES, /home/claudio/Music is a directory.
[claudio@nowhere ~]$ touch "empty file.txt"
[claudio@nowhere ~]$ ISDIR="$HOME/empty file.txt"
[claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
echo "YES, $ISDIR is a directory." ||
echo "Sorry, $ISDIR is not a directoy"
Sorry, /home/claudio/empty file.txt is not a directory
file="foo"
if [[ -e "$file" ]]; then echo "File Exists"; fi;
Jeśli chcesz sprawdzić, czy katalog istnieje, niezależnie od tego, czy jest to prawdziwy katalog, czy dowiązanie symboliczne, użyj tego:
ls $DIR
if [ $? != 0 ]; then
echo "Directory $DIR already exists!"
exit 1;
fi
echo "Directory $DIR does not exist..."
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”.
if ! ls $DIR 2>/dev/null; then echo "$DIR does not exist!"; fi
(1)
[ -d Piyush_Drv1 ] && echo ""Exists"" || echo "Not Exists"
(2)
[ `find . -type d -name Piyush_Drv1 -print | wc -l` -eq 1 ] && echo Exists || echo "Not Exists"
(3)
[[ -d run_dir && ! -L run_dir ]] && echo Exists || echo "Not Exists"
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
[[ `ls -ld SAMPLE_DIR| grep ^d | wc -l` -eq 1 ]] && echo exists || not exists
-ksh: not: not found [Brak takiego pliku lub katalogu]
Istnieją świetne rozwiązania, ale ostatecznie każdy skrypt zawiedzie, jeśli nie znajdziesz się w odpowiednim katalogu. Więc kod taki:
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
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ę:
dir=" "
echo "Input directory name to search for:"
read dir
find $HOME -name $dir -type d
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ć.
locate
ale nie dla niczego innego ...
--
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.