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 $DIRECTORYnie 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 mkdirtak 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 $DIRECTORYustawionym 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 && otherjest 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 ifstruktury 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"
fiProsty 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 tempdirjest już obecny. Następnie mkdir tempdirwyś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 filePrawda, jeśli plik istnieje i jest katalogiem.
Na przykład:
test -d "/etc" && echo Exists || echo Does not exist
Uwaga: testpolecenie jest takie samo jak wyrażenie warunkowe [(patrz man [:), więc jest przenośne w skryptach powłoki.
[- To jest synonimtestwbudowanego, ale ostatni argument musi być dosłowny], aby pasował do otwarcia[.
Aby uzyskać dostępne opcje lub dalszą pomoc, sprawdź:
help [help testman 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.
cdwyś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 cdwewną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 ksh93man:
${parameter:?word}
Jeśli
parameterjest ustawiony i jest różny od zera, wówczas podstaw jego wartość; w przeciwnym razie wydrukujwordi wyjdź z powłoki (jeśli nie jest interaktywny). Jeśliwordzostanie 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ż wordmoż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 setnie jest wystarczający, więc powiększam typ oczekiwanej tutaj pathnamewartoś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 -dtaka, jak wyjaśniono @Grundlefleck.
test -d /unreadable/existszawiedzie, 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
spacepo [-> [`` -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
findSprawdź 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".
fiSprawdź 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.
fiObie 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.
fifind -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, ifzamiast 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, pushdistnieje, wprowadzisz ją i zakończysz za pomocą 0, co oznacza, że thenczęść 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 thenblok 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 thenwykonanie 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 -esprawdzi, 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 -pktó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 fileprogramu. 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
lsPolecenia 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 -lwyjścia jest zwykle a dlub -myślnik. W przypadku djednego z wymienionych jest na pewno katalog.
Poniższe polecenie w jednym wierszu powie ci, czy dana ISDIRzmienna 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 lsrozkazem; 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ć.
locateale 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.