Chcę sprawdzić, czy katalog nie zawiera żadnych plików. Jeśli tak, pominę trochę przetwarzania.
Próbowałem następujące:
if [ ./* == "./*" ]; then
echo "No new file"
exit 1
fi
Daje to następujący błąd:
line 1: [: too many arguments
Czy istnieje rozwiązanie / alternatywa?
Odpowiedzi:
Byłoby również fajnie sprawdzić, czy katalog istnieje wcześniej.
źródło
&&
i||
jednocześnie! Jeśliecho "Not Empty"
zawiedzie,echo "Empty"
uruchomi się! Spróbujecho "test" && false || echo "fail"
! Tak, wiem,echo
że nie zawiedzie, ale jeśli zmienisz jakiekolwiek inne polecenie, będziesz zaskoczony![ "$(ls -A /)" ] && touch /non-empty || echo "Empty"
- jeśli chcesz „oznaczyć” niepuste katalogi utworzonym plikiem o nazwienon-empty
, zawiedzie i wyświetli „Pusty”.touch /empty
moja linia?if [ -n "$(ls -A /path/to/dir)" ]; then
... Zaktualizuj odpowiedź, zanim ktoś wklei ten kod na swój serwer, a haker wymyśli, jak go wykorzystać. Jeśli/path/to/dir
nie jest pusty, wówczas nazwy plików są przekazywane jako argumenty, do/bin/test
których wyraźnie nie jest przeznaczony. Wystarczy dodać-n
argument, problem rozwiązany. Dzięki!Nie ma potrzeby liczenia czegokolwiek ani globusów powłoki. Możesz także używać
read
w połączeniu zfind
. Jeślifind
dane wyjściowe są puste, zwróciszfalse
:To powinno być przenośne.
źródło
echo
połączenia odzwierciedlają zły wynik: w moim teście (pod Cygwinem)find . -mindepth 1 | read
miałem 141 kod błędu w niepustym katalogu, a 0 w pustym kataloguread
zwraca 0, a dla pustego 1.set -o pipefail
źródło
-n
jest poprawny i bezpieczny (przetestuj w katalogu ze spacjami w nazwie, przetestuj w niepustym katalogu o nazwie „0 = 1”).... [ -n "$(find "$DIR_TO_CHECK" -maxdepth 0 -type d -empty 2>/dev/null)" ]; ...
grep
. serverfault.com/questions/225798find "$DIR_TO_CHECK" -maxdepth 0 -type d -empty | grep .
i polegać na statusie wyjścia z grep. Niezależnie od tego, jak to zrobisz, jest to odpowiednia odpowiedź na to pytanie.źródło
Spowoduje to wykonanie zadania w bieżącym katalogu roboczym (.):
lub to samo polecenie podzielone na trzy linie, aby było bardziej czytelne:
Wystarczy wymienić
ls -1A . | wc -l
zels -1A <target-directory> | wc -l
jeśli trzeba uruchomić go na innym folderze docelowym.Edit : Wymieniłem
-1a
z-1A
(patrz @Daniel komentarz)źródło
ls -A
zamiast tego. Niektóre systemy plików nie posiada.
i..
dowiązania symboliczne według docs.-1
jest zdecydowanie zbędny. Nawet jeślils
nie wydrukuje jednego elementu w wierszu, gdy zostanie potokowany, nie ma to wpływu na pomysł sprawdzenia, czy wygenerował zero lub więcej wierszy.Użyj następujących opcji:
W ten sposób jesteś niezależny od formatu wyjściowego
ls
.-mindepth
pomija sam katalog,-maxdepth
zapobiega rekurencyjnej obronie w podkatalogach w celu przyspieszenia.źródło
wc -l
ifind
format (co jest dość prosty choć).Za pomocą tablicy:
źródło
shopt -s nullglob
${#files[@]} == 2
Założenie nie wytrzymuje do głównego katalogu (prawdopodobnie nie będzie sprawdzić, czy jest ona pusta, ale niektóre kod, który nie wie o tym ograniczeniem może).Hacky, ale tylko bash, wolny od PID sposób:
Wykorzystuje to fakt, że
test
wbudowane wyjście kończy się na 2, jeśli podano więcej niż jeden argument po-e
: Po pierwsze,"$1"/*
glob jest rozwijany przez bash. Daje to jeden argument na plik. WięcJeśli nie ma plików, gwiazdka w
test -e "$1"*
nie rozwija się, więc Shell wraca do próby pliku o nazwie*
, która zwraca 1.... z wyjątkiem tego, że tak naprawdę istnieje jeden plik o nazwie dokładnie
*
, to gwiazdka rozwija się do well, gwiazdka, która kończy się tak samo jak powyżej, tj.test -e "dir/*"
, właśnie ten czas zwraca 0. (Dzięki @TrueY za zwrócenie na to uwagi.)Jeśli jest jeden plik,
test -e "dir/file"
uruchamiany jest, który zwraca 0.Ale jeśli jest więcej plików niż 1,
test -e "dir/file1" "dir/file2"
uruchamiany jest bash, który zgłasza to jako błąd użycia, tj. 2.case
otacza całą logikę, dzięki czemu tylko pierwszy przypadek z 1 statusem wyjścia jest zgłaszany jako sukces.Możliwe problemy, których nie sprawdziłem:
Jest więcej plików niż liczba dozwolonych argumentów - myślę, że może to zachowywać się podobnie jak w przypadku plików 2+.
Albo istnieje plik z pustą nazwą - nie jestem pewien, czy jest to możliwe na żadnym rozsądnym OS / FS.
źródło
test -e dir/*
jest wywoływany. Jeśli jedynym plikiem jest „*” w katalogu, test zwróci 0. Jeśli jest więcej plików, wówczas zwraca 2. Więc działa tak, jak opisano.Z FIND (1) (w Linuksie i FreeBSD) możesz nierekurencyjnie patrzeć na pozycję katalogu przez „-maxdepth 0” i sprawdzić, czy jest pusta za pomocą „-empty”. W odniesieniu do pytania daje to:
źródło
Myślę, że najlepszym rozwiązaniem jest:
dzięki https://stackoverflow.com/a/91558/520567
To jest anonimowa edycja mojej odpowiedzi, która może, ale nie musi być pomocna dla kogoś: niewielka zmiana daje liczbę plików:
Działa to poprawnie, nawet jeśli nazwy plików zawierają spacje.
źródło
EDYCJA: Myślę, że to rozwiązanie działa dobrze z gnu find, po szybkim spojrzeniu na implementację . Ale to może nie działać na przykład z znalezieniem netbsd . Rzeczywiście, ten używa pola st_size stat (2). Podręcznik opisuje to jako:
Lepszym rozwiązaniem, również prostszym, jest:
Również -prune w 1. rozwiązaniu jest bezużyteczne.
EDYCJA: nie -exit dla gnu find .. powyższe rozwiązanie jest dobre dla znalezienia NetBSD. W przypadku wyszukiwania GNU powinno to działać:
źródło
-exit
predykatu .To wszystko wspaniałe rzeczy - właśnie zrobiłem to ze skryptu, aby sprawdzić puste katalogi poniżej bieżącego. Poniższe należy umieścić w pliku o nazwie „findempty”, umieścić gdzieś w ścieżce, aby bash mógł go znaleźć, a następnie uruchomić chmod 755. Sądzę, że można je łatwo dostosować do konkretnych potrzeb.
źródło
Ta praca dla mnie
../IN
polega na sprawdzaniu i przetwarzaniu plików w katalogu , biorąc pod uwagę, że skrypt znajduje się w../Script
katalogu:źródło
Co z testowaniem, czy katalog istnieje i nie jest pusty w instrukcji if
źródło
W przypadku dowolnego katalogu innego niż bieżący możesz sprawdzić, czy jest pusty, próbując
rmdir
go otworzyć, ponieważrmdir
w przypadku niepustych katalogów z pewnością wystąpi błąd. Jeśli sięrmdir
powiedzie i rzeczywiście chcesz, aby pusty katalog przetrwał test, po prostumkdir
to znowu.Nie używaj tego hacka, jeśli istnieją inne procesy, które mogą zostać rozczłonkowane przez katalog, o którym wiedzą, że na krótko przestają istnieć.
Jeśli
rmdir
to nie zadziała, a być może testujesz katalogi, które potencjalnie mogą zawierać dużą liczbę plików, każde rozwiązanie oparte na globowaniu powłoki może się spowolnić i / lub przekroczyć limity długości wiersza poleceń. Prawdopodobnie lepiej użyćfind
w takim przypadku.find
Tak wygląda najszybsze rozwiązanie, jakie mogę wymyślićDziała to w wersjach GNU i BSD,
find
ale nie w wersji Solaris, której brakuje każdego z tychfind
operatorów. Kochaj swoją pracę, Oracle.źródło
Możesz spróbować usunąć katalog i poczekać na błąd; rmdir nie usunie katalogu, jeśli nie jest pusty.
źródło
rmdir
zakończy się niepowodzeniem, jeśli nie będę mieć uprawnień do usunięcia katalogu; lub jeśli jest to podobjętość Btrfs; lub jeśli należy do systemu plików tylko do odczytu. A jeślirmdir
nie zawiedzie imkdir
uruchomi się: co jeśli już usunięty katalog należał do innego użytkownika? co z jego (być może niestandardowymi) uprawnieniami? ACL? rozszerzone atrybuty? Wszystko stracone.