Jak na podstawie skryptu powłoki sprawdzić, czy katalog zawiera pliki?
Coś podobnego do tego
if [ -e /some/dir/* ]; then echo "huzzah"; fi;
ale który działa, jeśli katalog zawiera jeden lub kilka plików (powyższy działa tylko z dokładnie 0 lub 1 plikami).
Odpowiedzi:
Z dotychczasowych rozwiązań korzystają
ls
. Oto rozwiązanie obejmujące wszystko bash:źródło
shopt -q nullglob || resetnullglob=1; shopt -s nullglob; shopt -q dotglob || resetdotglob=1; shopt -s dotglob; files=(/some/dir/*); [ "$files" ] && echo "wowzers"; [ "$resetdotglob" ] && shopt -u dotglob; [ "$resetnullglob" ] && shopt -u nullglob;
files=$(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*)
files=$(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*)
wtedy instrukcja if powinna zmienić się na,if [ ${#files} -gt 0 ];
a może po prostu zapomniałeś () wokół polecenia podpowłoki?files=($(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*))
Trzy najlepsze sztuczki
shopt -s nullglob dotglob; f=your/dir/*; ((${#f}))
Ta sztuczka jest w 100%
bash
i wywołuje (spawnuje) podpowłokę. Pomysł pochodzi od Bruno De Fraine i został ulepszony komentarzem teamboba .Uwaga: nie ma różnicy między pustym katalogiem a katalogiem nieistniejącym (nawet jeśli podana ścieżka jest plikiem).
Podobna alternatywa i więcej szczegółów (i więcej przykładów) znajduje się w „oficjalnym” FAQ kanału #bash IRC :
[ -n "$(ls -A your/dir)" ]
Ta sztuczka została zainspirowana artykułem nixCraft opublikowanym w 2007 roku. Dodaj,
2>/dev/null
aby wyeliminować błąd wyjściowy"No such file or directory"
.Zobacz także odpowiedź Andrew Taylora (2008) i odpowiedź gr8can8diana (2011).
lub jednowierszowa wersja bashism:
Uwaga:
ls
zwraca,$?=2
gdy katalog nie istnieje. Ale nie ma różnicy między plikiem a pustym katalogiem.[ -n "$(find your/dir -prune -empty)" ]
Ta ostatnia sztuczka jest inspirowana z odpowiedzią gravstar w którym
-maxdepth 0
zastępuje się-prune
i poprawił się o phils komentarzu „s.odmiana wykorzystująca
-type d
:Wyjaśnienie:
find -prune
jest podobny dofind -maxdepth 0
użycia mniejszej liczby znakówfind -empty
wypisuje puste katalogi i plikifind -type d
drukuje tylko katalogiUwaga: możesz również zastąpić
[ -n "$(find your/dir -prune -empty)" ]
poniższą skróconą wersją:Ten ostatni kod działa w większości przypadków, ale należy pamiętać, że złośliwe ścieżki mogą wyrażać polecenie ...
źródło
[ -n "$(find "your/dir" -prune -empty)" ]
, aby uniknąć powtarzania ścieżki katalogu.if [ ``ls -A your/dir`` ]
w skrypcie, doszedłem do wniosku, że działa dobrze w przypadku katalogu z 0, 1 lub 2 podkatalogami, ale nie działa w przypadku katalogu z więcej niż 2 podkatalogami.line 17: [: 20150424-002813: unary operator expected
gdzie20150424-002813
była jedna z nazw katalogów. Użyto powłoki/bin/bash/
. W końcu zmieniłem to nals "$destination" | tail -1
if [ ``ls -A my/dir`` ]
wychodzi na błądbash: [: -A: binary operator expected
. Testowane na bash w wersjach 4.1.2 i 4.2.53.-n
wariant był w nagłówku, ale nie w akapicie poniżej). Więc tak, w porządku.ls: cannot access '/path': No such file or directory
. Czy jest sposób, aby ukryć tę wiadomość? Chciałbym tam po cichu zawieść.A co z następującymi:
Dzięki temu nie ma potrzeby generowania pełnej listy zawartości katalogu.
read
Jest zarówno do wyjścia wyrzucić i zrobić wyrażenie ocenić wartość true tylko wtedy, gdy coś jest odczytywany (czyli/some/dir/
znajduje się pustafind
).źródło
find /some/dir/ -maxdepth 0 -empty -exec echo "huzzah" \;
ls
wyjściowych i nie opiera się na innych niż domyślne funkcje powłoki.-maxdepth
i-empty
prawyborach.Próbować:
źródło
/bin/ls <some_dir>/* 2> /dev/null
if [! -z "$ tmp"]; potem echo Coś tam jest fils /some/dir/*
]; potem echo "huzzah"; fi-n
zamiast! -z
(oba są równoważne, ale dlaczego nie użyć krótszej formy, jeśli istnieje).BigGray% if [ ! -z
ls / some / dir / * `]; potem echo "huzzah"; fi zsh: nie znaleziono dopasowań: / some / dir / * `ls...
w bashźródło
Uważaj na katalogi z dużą ilością plików! Ocena
ls
polecenia może zająć trochę czasu .IMO najlepszym rozwiązaniem jest to, które używa
źródło
źródło
Czy mógłbyś porównać wyniki tego?
źródło
Kilka uwag dotyczących implementacji:
for
Pętla unika połączenia do zewnętrznegols
procesu. Nadal odczytuje wszystkie wpisy katalogu raz. Można to zoptymalizować tylko poprzez napisanie programu w C, który jawnie używa readdir ().test -e
Wewnątrz pętli łapie przypadku pustego katalogu, w którym to przypadku zmienna_ief
będzie przypisana wartość „katalog / *”. Tylko jeśli ten plik istnieje, funkcja zwróci „niepusty”test
implementacja nie obsługuje-e
flagi.źródło
dotglob
nie jest ustawione -shopt -s dotglob
To mówi mi, czy katalog jest pusty, a jeśli nie, liczba plików, które zawiera.
źródło
ls
.To może być bardzo późna odpowiedź, ale oto rozwiązanie, które działa. Ta linia rozpoznaje tylko istnienie plików! Nie da ci fałszywego pozytywnego wyniku, jeśli katalogi istnieją.
źródło
Zakładam, że nie masz plik o nazwie
*
się/any/dir/you/check
, to powinno działać nabash
dash
posh
busybox sh
azsh
jednak (na zsh) wymagaćunsetopt nomatch
.Wydajność powinna być porównywalna do każdej
ls
używającej*
(glob), myślę, że będzie wolna w katalogach z wieloma węzłami (mój/usr/bin
z ponad 3000 plików nie poszedł tak wolno), zużyje przynajmniej tyle pamięci, aby przydzielić wszystkie katalogi / nazwy plików (i więcej) ponieważ wszystkie są przekazywane (rozwiązywane) do funkcji jako argumenty, niektóre powłoki prawdopodobnie mają ograniczenia co do liczby argumentów i / lub długości argumentów.Przydałaby się przenośna, szybka metoda O (1) zero zasobów do sprawdzenia, czy katalog jest pusty.
aktualizacja
Wersja powyżej nie stanowią ukrytych plików / katalogów, w razie konieczności kilka testów, jak
is_empty
z sh Richa (POSIX Shell) sztuczki :Ale zamiast tego myślę o czymś takim:
Trochę obawy o końcowe ukośniki różnice w argumencie i wynikach wyszukiwania, gdy katalog jest pusty, i końcowe znaki nowej linii (ale powinno to być łatwe do obsłużenia), niestety w moim
busybox
sh
programie jest to prawdopodobnie błąd wfind -> dd
potoku z wyjściem obciętym losowo ( jeśli użyłemcat
wyjście jest zawsze takie samo, wydaje się, że jestdd
z argumentemcount
).źródło
is_empty(){ [ ! -d "${1}" ] && return 2;set -- "${1}" "${1}"/* "${1}"/.[!.]* "${1}"/..?*;[ "${*}" = "${1} ${1}/* ${1}/.[!.]* ${1}/..?*" ]; };
ZSH
Wiem, że pytanie było przeznaczone do basha; ale tylko w celach informacyjnych dla użytkowników zsh :
Sprawdź, czy katalog nie jest pusty
Aby sprawdzić, czy
foo
jest niepusty:gdzie, jeśli
foo
nie jest pusta, kod wfor
bloku zostanie wykonany.Sprawdź, czy katalog jest pusty
Aby sprawdzić, czy
foo
jest pusty:gdzie, jeśli
foo
jest puste, kod wfor
bloku zostanie wykonany.Uwagi
Nie
foo
musieliśmy cytować powyższego katalogu , ale możemy to zrobić, jeśli zajdzie taka potrzeba:Możemy również przetestować więcej niż jeden obiekt, nawet jeśli nie jest to katalog:
Wszystko, co nie jest katalogiem, zostanie po prostu zignorowane.
Dodatki
Ponieważ globujemy, możemy użyć dowolnego globu (lub rozwinięcia nawiasów):
Możemy również zbadać obiekty umieszczone w tablicy. Z katalogami jak wyżej, na przykład:
W ten sposób możemy testować obiekty, które mogą już być ustawione w parametrze tablicy.
Zauważ, że kod w
for
bloku jest oczywiście wykonywany po kolei w każdym katalogu. Jeśli nie jest to pożądane, możesz po prostu wypełnić parametr tablicy, a następnie operować na tym parametrze:Wyjaśnienie
Dla użytkowników zsh istnieje
(F)
kwalifikator glob (zobaczman zshexpn
), który dopasowuje „pełne” (niepuste) katalogi:Kwalifikator
(F)
wyświetla listę zgodnych obiektów: jest katalogiem ORAZ nie jest pusty. Tak więc(^F)
pasuje: nie jest katalogiem LUB jest puste. W związku z tym(^F)
, na przykład , sam wyświetlałby również zwykłe pliki. Tak więc, jak wyjaśniono nazshexp
stronie podręcznika , potrzebujemy również(/)
kwalifikatora glob, który zawiera tylko katalogi:Dlatego, aby sprawdzić, czy dany katalog jest pusty, możesz uruchomić:
i tylko po to, aby mieć pewność, że niepusty katalog nie zostanie przechwycony:
Ups! Ponieważ
Y
nie jest puste, zsh nie znajduje żadnych dopasowań dla(/^F)
(„katalogi, które są puste”) i dlatego wypluwa komunikat o błędzie informujący, że nie znaleziono żadnych dopasowań dla globu. Dlatego musimy pomijać te możliwe komunikaty o błędach za pomocą(N)
kwalifikatora glob:Dlatego dla pustych katalogów potrzebujemy kwalifikatora
(N/^F)
, który można odczytać jako: „nie ostrzegaj mnie o awariach, katalogach, które nie są pełne”.Podobnie, dla niepustych katalogów potrzebujemy kwalifikatora
(NF)
, który możemy również odczytać jako: "nie ostrzegaj mnie o awariach, pełne katalogi".źródło
Dziwię się, że nie wspomniano o przewodniku wełnianym o pustych katalogach . Ten przewodnik, a tak naprawdę wszystko to, co dotyczy wooledge, jest lekturą obowiązkową w przypadku pytań dotyczących typu muszli.
Warto zauważyć z tej strony:
źródło
Mała odmiana odpowiedzi Bruno :
Mi to pasuje
źródło
Biorąc wskazówkę (lub kilka) z odpowiedzi Olibre, podoba mi się funkcja Bash:
Ponieważ podczas gdy tworzy jedną podpowłokę, jest tak blisko rozwiązania O (1), jak mogę sobie wyobrazić, a nadanie mu nazwy sprawia, że jest czytelny. Mogę wtedy pisać
Jeśli chodzi o O (1), istnieją przypadki odstające: jeśli z dużego katalogu usunięto wszystkie lub wszystkie wpisy oprócz ostatniego, „find” może być zmuszony do przeczytania całości, aby określić, czy jest pusty. Uważam, że oczekiwana wydajność to O (1), ale w najgorszym przypadku rozmiar katalogu jest liniowy. Nie mierzyłem tego.
źródło
Jak dotąd nie widziałem odpowiedzi używającej grep, która, jak sądzę, dałaby prostszą odpowiedź (bez zbyt wielu dziwnych symboli!). Oto, jak mógłbym sprawdzić, czy w katalogu istnieją jakieś pliki przy użyciu powłoki Bourne:
zwraca liczbę plików w katalogu:
możesz wpisać ścieżkę do katalogu, w którym zapisany jest katalog. Pierwsza połowa potoku zapewnia, że pierwszym znakiem wyjścia dla każdego pliku jest „-”. Następnie egrep zlicza liczbę wierszy zaczynających się od tego symbolu, używając wyrażeń regularnych. teraz wszystko, co musisz zrobić, to zapisać uzyskaną liczbę i porównać ją za pomocą odwrotnych cudzysłowów, takich jak:
x to dowolna zmienna.
źródło
Mieszając suszone śliwki i ostatnie odpowiedzi, muszę
działa to również w przypadku ścieżek ze spacjami
źródło
Prosta odpowiedź z bashem :
źródło
Poszedłbym na
find
:To sprawdza wynik wyszukiwania tylko plików w katalogu, bez przechodzenia przez podkatalogi. Następnie sprawdza wyjście używając
-z
opcji wziętej zman test
:Zobacz niektóre wyniki:
Pusty reż:
Po prostu dirs w tym:
Plik w katalogu:
Plik w podkatalogu:
źródło
Z pewnym obejściem mogłem znaleźć prosty sposób na sprawdzenie, czy w katalogu są pliki. Można to rozszerzyć o więcej za pomocą poleceń grep, aby sprawdzić konkretnie pliki .xml lub .txt itp. Np .:
ls /some/dir | grep xml | wc -l | grep -w "0"
źródło
źródło
nullglob
, ponieważ wtedyls
polecenie się powiedzie.aby przetestować określony katalog docelowy
źródło
Spróbuj poleceniem znajdź. Określ katalog na stałe lub jako argument. Następnie rozpocznij wyszukiwanie, aby przeszukać wszystkie pliki w katalogu. Sprawdź, czy zwrot find ma wartość null. Powtórz dane znalezienia
źródło
Nie podoba mi się
ls - A
zamieszczone rozwiązania. Najprawdopodobniej chcesz sprawdzić, czy katalog jest pusty, ponieważ nie chcesz go usuwać. Następujące osoby to robią. Jeśli jednak chcesz po prostu zarejestrować pusty plik, z pewnością usunięcie i ponowne utworzenie go jest szybsze niż wyświetlenie prawdopodobnie nieskończonych plików?To powinno działać ...
źródło
${target}/..
.U mnie dobrze to działa (gdy reż istnieje):
Z pełną kontrolą:
źródło