Sprawdzanie ze skryptu powłoki, czy katalog zawiera pliki


116

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).


Na co warto twój przykład, dobry robi to, co chcesz w ksh i zsh
Dave Webb

2
@DaveWebb Nie, nie ma. Jeśli glob rozszerza się do więcej niż jednego słowa, test zsh zgłasza „test: zbyt wiele argumentów”.
Jens,

„huzzah” oznacza „katalog nie jest pusty”.
funroll

Jeśli katalog zawiera tylko pusty podkatalog, czy liczy się to jako „zawierające pliki”?
Keith Thompson

Odpowiedzi:


72

Z dotychczasowych rozwiązań korzystają ls. Oto rozwiązanie obejmujące wszystko bash:

#!/bin/bash
shopt -s nullglob dotglob     # To include hidden files
files=(/some/dir/*)
if [ ${#files[@]} -gt 0 ]; then echo "huzzah"; fi

8
o ile będziesz pamiętać o przywróceniu opcji do ich pierwotnej wartości na końcu skryptu :)
Jean

To jest nieco ulepszona wersja, która zajmuje się resetowaniem ustawień basha: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;
user123444555621

12
Dlaczego nie użyć podpowłoki, aby zresetować ustawienia:files=$(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*)
teambob

7
@teambob, jeśli używasz podpowłoki: 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/*))
stoutyhk

2
@stoutyhk $ (...) przywraca ustawienia, nie jest wymagana osobna podpowłoka. Użycie $ (...) powoduje utworzenie nowej instancji powłoki. Środowisko tej nowej instancji jest wyrzucane po zakończeniu polecenia. Edycja: znaleziono odniesienie tldp.org/LDP/abs/html/commandsub.html „Zastępowanie polecenia wywołuje podpowłokę”.
teambob

140

Trzy najlepsze sztuczki


shopt -s nullglob dotglob; f=your/dir/*; ((${#f}))

Ta sztuczka jest w 100% bashi wywołuje (spawnuje) podpowłokę. Pomysł pochodzi od Bruno De Fraine i został ulepszony komentarzem teamboba .

files=$(shopt -s nullglob dotglob; echo your/dir/*)
if (( ${#files} ))
then
  echo "contains files"
else 
  echo "empty (or does not exist or is a file)"
fi

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 :

if (shopt -s nullglob dotglob; f=(*); ((${#f[@]})))
then
  echo "contains files"
else 
  echo "empty (or does not exist, or is a file)"
fi

[ -n "$(ls -A your/dir)" ]

Ta sztuczka została zainspirowana artykułem nixCraft opublikowanym w 2007 roku. Dodaj, 2>/dev/nullaby wyeliminować błąd wyjściowy "No such file or directory".
Zobacz także odpowiedź Andrew Taylora (2008) i odpowiedź gr8can8diana (2011).

if [ -n "$(ls -A your/dir 2>/dev/null)" ]
then
  echo "contains files (or is a file)"
else
  echo "empty (or does not exist)"
fi

lub jednowierszowa wersja bashism:

[[ $(ls -A your/dir) ]] && echo "contains files" || echo "empty"

Uwaga: ls zwraca, $?=2gdy 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 0zastępuje się -prunei poprawił się o phils komentarzu „s.

if [ -n "$(find your/dir -prune -empty 2>/dev/null)" ]
then
  echo "empty (directory or file)"
else
  echo "contains files (or does not exist)"
fi

odmiana wykorzystująca -type d:

if [ -n "$(find your/dir -prune -empty -type d 2>/dev/null)" ]
then
  echo "empty directory"
else
  echo "contains files (or does not exist or is not a directory)"
fi

Wyjaśnienie:

  • find -prunejest podobny do find -maxdepth 0użycia mniejszej liczby znaków
  • find -empty wypisuje puste katalogi i pliki
  • find -type d drukuje tylko katalogi

Uwaga: możesz również zastąpić [ -n "$(find your/dir -prune -empty)" ]poniższą skróconą wersją:

if [ `find your/dir -prune -empty 2>/dev/null` ]
then
  echo "empty (directory or file)"
else
  echo "contains files (or does not exist)"
fi

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 ...


2
Myślę, że możesz uprościć opcję wyszukiwania [ -n "$(find "your/dir" -prune -empty)" ], aby uniknąć powtarzania ścieżki katalogu.
phils

Używając 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 expectedgdzie 20150424-002813była jedna z nazw katalogów. Użyto powłoki /bin/bash/. W końcu zmieniłem to nals "$destination" | tail -1
Christophe De Troyer

Cześć @ChristopheDeTroyer Nie mogę odtworzyć twojego problemu. Z mojej strony if [ ``ls -A my/dir`` ]wychodzi na błąd bash: [: -A: binary operator expected. Testowane na bash w wersjach 4.1.2 i 4.2.53.
olibre

1
Cóż, motywacją do komentowania była głównie zauważona niespójność (ponieważ -nwariant był w nagłówku, ale nie w akapicie poniżej). Więc tak, w porządku.
maxschlepzig

1
Używam twojego rozwiązania -n, mój skrypt wciąż narzeka na to ls: cannot access '/path': No such file or directory. Czy jest sposób, aby ukryć tę wiadomość? Chciałbym tam po cichu zawieść.
Freedo,

48

A co z następującymi:

if find /some/dir/ -maxdepth 0 -empty | read v; then echo "Empty dir"; fi

Dzięki temu nie ma potrzeby generowania pełnej listy zawartości katalogu. readJest zarówno do wyjścia wyrzucić i zrobić wyrażenie ocenić wartość true tylko wtedy, gdy coś jest odczytywany (czyli /some/dir/znajduje się pusta find).


3
lub po prostufind /some/dir/ -maxdepth 0 -empty -exec echo "huzzah" \;
doubleDown

5
+1 To najbardziej eleganckie rozwiązanie. Nie wymaga przetwarzania danych lswyjściowych i nie opiera się na innych niż domyślne funkcje powłoki.

7
Opiera się jednak na niestandardowych -maxdepthi -emptyprawyborach.
chepner

21

Próbować:

if [ ! -z `ls /some/dir/*` ]; then echo "huzzah"; fi

U mnie to zadziałało, ale nie mogę sformatować tego d * mn wiadomości !!! <br> eksportuj tmp = /bin/ls <some_dir>/* 2> /dev/nullif [! -z "$ tmp"]; potem echo Coś tam jest fi
AndrewStone,

1
Dla idiotów Basha takich jak ja, jeśli chcesz sprawdzić coś przeciwnego - czy katalog jest pusty - użyj if [-z ls /some/dir/*]; potem echo "huzzah"; fi
Chris Moschini

4
Możesz użyć -nzamiast ! -z(oba są równoważne, ale dlaczego nie użyć krótszej formy, jeśli istnieje).
n.st

Ponieważ ZSH ten przykład zgłasza błąd, chodzi o to, aby ten błąd nie był wyrzucany ... BigGray% if [ ! -z ls / some / dir / * `]; potem echo "huzzah"; fi zsh: nie znaleziono dopasowań: / some / dir / * `
Hvisage

nie działa dla mnie bez podwójnych cudzysłowów ls...w bash
letmutx

15
# Works on hidden files, directories and regular files
### isEmpty()
# This function takes one parameter:
# $1 is the directory to check
# Echoes "huzzah" if the directory has files
function isEmpty(){
  if [ "$(ls -A $1)" ]; then
    echo "huzzah"
  else 
    echo "has no files"
  fi
}

15

Uważaj na katalogi z dużą ilością plików! Ocena lspolecenia może zająć trochę czasu .

IMO najlepszym rozwiązaniem jest to, które używa

find /some/dir/ -maxdepth 0 -empty


6

Czy mógłbyś porównać wyniki tego?

 ls -A /some/dir | wc -l

4
# Sprawdza, czy katalog zawiera nieukryte pliki.
#
# użycie: if isempty "$ HOME"; następnie echo „Witaj w domu”; fi
#
jest pusty() {
    za _ief w 1 $ / *; robić
        if [-e "$ _ief"]; następnie
            powrót 1
        fi
    Gotowe
    powrót 0
}

Kilka uwag dotyczących implementacji:

  • forPętla unika połączenia do zewnętrznego lsprocesu. Nadal odczytuje wszystkie wpisy katalogu raz. Można to zoptymalizować tylko poprzez napisanie programu w C, który jawnie używa readdir ().
  • test -eWewnątrz pętli łapie przypadku pustego katalogu, w którym to przypadku zmienna _iefbędzie przypisana wartość „katalog / *”. Tylko jeśli ten plik istnieje, funkcja zwróci „niepusty”
  • Ta funkcja będzie działać we wszystkich implementacjach POSIX. Należy jednak pamiętać, że Solaris / bin / sh nie należy do tej kategorii. Jego testimplementacja nie obsługuje -eflagi.

1
Zignorowałoby to dotfiles w katalogu, jeśli dotglobnie jest ustawione -shopt -s dotglob
l0b0

4

To mówi mi, czy katalog jest pusty, a jeśli nie, liczba plików, które zawiera.

directory="/some/dir"
number_of_files=$(ls -A $directory | wc -l)

if [ "$number_of_files" == "0" ]; then
    echo "directory $directory is empty"
else
    echo "directory $directory contains $number_of_files files"
fi

Czy ktoś może mi wyjaśnić, dlaczego zostałem odrzucony? Jeśli piszę craps, chciałbym wiedzieć dlaczego;)
Daishi

1
Nie przegłosowałem tego, ale przypuszczam, że dzieje się tak dlatego, że analizujesz wyjściels .
Toby Speight

czy powiązany artykuł jest niejasny? Jeśli tak, napisz do autora (nie do mnie).
Toby Speight

1
@TobySpeight Rozumiem o co chodzi. Ale w tym przypadku liczę wiersze, nie wyliczając ich. Powinien dawać fałszywy wynik tylko wtedy, gdy nazwa pliku zawiera nowy wiersz. A jeśli nazwy plików zawierają nowe linie, coś znacznie ważniejszego musi gdzieś spieprzyć;)
Daishi

3

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ą.

if find /path/to/check/* -maxdepth 0 -type f | read
  then echo "Files Exist"
fi

2
dir_is_empty() {
   [ "${1##*/}" = "*" ]
}

if dir_is_empty /some/dir/* ; then
   echo "huzzah"
fi

Zakładam, że nie masz plik o nazwie *się /any/dir/you/check, to powinno działać na bash dash posh busybox sha zshjednak (na zsh) wymagać unsetopt nomatch.

Wydajność powinna być porównywalna do każdej lsużywającej *(glob), myślę, że będzie wolna w katalogach z wieloma węzłami (mój /usr/binz 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_emptyz sh Richa (POSIX Shell) sztuczki :

is_empty () (
cd "$1"
set -- .[!.]* ; test -f "$1" && return 1
set -- ..?* ; test -f "$1" && return 1
set -- * ; test -f "$1" && return 1
return 0 )

Ale zamiast tego myślę o czymś takim:

dir_is_empty() {
    [ "$(find "$1" -name "?*" | dd bs=$((${#1}+3)) count=1 2>/dev/null)" = "$1" ]
}

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 shprogramie jest to prawdopodobnie błąd w find -> ddpotoku z wyjściem obciętym losowo ( jeśli użyłem catwyjście jest zawsze takie samo, wydaje się, że jest ddz argumentem count).


Uwielbiam przenośne rozwiązanie. Przyszedłem, aby udzielić tej samej odpowiedzi. Właśnie napisałem to inaczej (zwróć 2, jeśli nie katalog). Ponadto te przenośne rozwiązania mają tę zaletę, że nie wywołują żadnych programów zewnętrznych, co może się liczyć jako plus w przypadku systemów z ograniczeniami lub systemów wbudowanych. Martwię się tylko, że użycie "()" może stworzyć nowy podproces (lub przynajmniej wymusić skopiowanie środowiska i rzeczy, a następnie przełączenie z powrotem). Spójrz na to: is_empty () {_d = "$ {1: -.}"; [! -d "$ {_ d}"] && return 2; set - "$ {_ d}" / * "$ {_ d}" /.[!.]* "$ {_ d}" /..?*; ["$ { }" = "$ {_ d} / $ {_ d} /. [!.] * $ {_ d} /..?*"]; };
Diego Augusto Molina

@DiegoAugustoMolina Ostatnio w projekcie musiałem zrobić ten test jeszcze raz, jeśli katalog był pusty, na początku użyłem pythona, to skoro pythona praktycznie zainstalowałem tylko po to, zaimplementowałem test w c, implementacja jest ekstremalna banał, zastanawiam się, dlaczego nigdy nie został dodany jako test lub jako samodzielne polecenie
Alex

1
Ja również ostatnio potrzebowałem rozwiązania tego problemu dla (naprawdę) ograniczonego systemu. Zoptymalizowałem nawet nieco poprzedni kod, aby nie używać żadnych dodatkowych zmiennych. Hackish i brzydko wyglądający jednolinijkowy, ale świetny. Służ sobie:is_empty(){ [ ! -d "${1}" ] && return 2;set -- "${1}" "${1}"/* "${1}"/.[!.]* "${1}"/..?*;[ "${*}" = "${1} ${1}/* ${1}/.[!.]* ${1}/..?*" ]; };
Diego Augusto Molina

2

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 foojest niepusty:

$ for i in foo(NF) ; do ... ; done

gdzie, jeśli foonie jest pusta, kod w forbloku zostanie wykonany.

Sprawdź, czy katalog jest pusty

Aby sprawdzić, czy foojest pusty:

$ for i in foo(N/^F) ; do ... ; done

gdzie, jeśli foojest puste, kod w forbloku zostanie wykonany.

Uwagi

Nie foomusieliśmy cytować powyższego katalogu , ale możemy to zrobić, jeśli zajdzie taka potrzeba:

$ for i in 'some directory!'(NF) ; do ... ; done

Możemy również przetestować więcej niż jeden obiekt, nawet jeśli nie jest to katalog:

$ mkdir X     # empty directory
$ touch f     # regular file
$ for i in X(N/^F) f(N/^F) ; do echo $i ; done  # echo empty directories
X

Wszystko, co nie jest katalogiem, zostanie po prostu zignorowane.

Dodatki

Ponieważ globujemy, możemy użyć dowolnego globu (lub rozwinięcia nawiasów):

$ mkdir X X1 X2 Y Y1 Y2 Z
$ touch Xf                    # create regular file
$ touch X1/f                  # directory X1 is not empty
$ touch Y1/.f                 # directory Y1 is not empty
$ ls -F                       # list all objects
X/ X1/ X2/ Xf Y/ Y1/ Y2/ Z/
$ for i in {X,Y}*(N/^F); do printf "$i "; done; echo  # print empty directories
X X2 Y Y2

Możemy również zbadać obiekty umieszczone w tablicy. Z katalogami jak wyżej, na przykład:

$ ls -F                       # list all objects
X/ X1/ X2/ Xf Y/ Y1/ Y2/ Z/
$ arr=(*)                     # place objects into array "arr"
$ for i in ${^arr}(N/^F); do printf "$i "; done; echo
X X2 Y Y2 Z

W ten sposób możemy testować obiekty, które mogą już być ustawione w parametrze tablicy.

Zauważ, że kod w forbloku 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:

$ for i in *(NF) ; do full_directories+=($i) ; done
$ do_something $full_directories

Wyjaśnienie

Dla użytkowników zsh istnieje (F)kwalifikator glob (zobacz man zshexpn), który dopasowuje „pełne” (niepuste) katalogi:

$ mkdir X Y
$ touch Y/.f        # Y is now not empty
$ touch f           # create a regular file
$ ls -dF *          # list everything in the current directory
f X/ Y/
$ ls -dF *(F)       # will list only "full" directories
Y/

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 na zshexpstronie podręcznika , potrzebujemy również (/)kwalifikatora glob, który zawiera tylko katalogi:

$ mkdir X Y Z
$ touch X/f Y/.f    # directories X and Y now not empty
$ for i in *(/^F) ; do echo $i ; done
Z

Dlatego, aby sprawdzić, czy dany katalog jest pusty, możesz uruchomić:

$ mkdir X
$ for i in X(/^F) ; do echo $i ; done ; echo "finished"
X
finished

i tylko po to, aby mieć pewność, że niepusty katalog nie zostanie przechwycony:

$ mkdir Y
$ touch Y/.f
$ for i in Y(/^F) ; do echo $i ; done ; echo "finished"
zsh: no matches found: Y(/^F)
finished

Ups! Ponieważ Ynie 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:

$ mkdir Y
$ touch Y/.f
$ for i in Y(N/^F) ; do echo $i ; done ; echo "finished"
finished

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".


1

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:

Nigdy nie próbuj analizować wyjścia ls. Nawet rozwiązania ls -A mogą się zepsuć (np. W HP-UX, jeśli jesteś rootem, ls -A robi dokładnie odwrotność tego, co robi, jeśli nie jesteś rootem - i nie, nie mogę wymyślić czegoś tak niewiarygodnie głupi).

W rzeczywistości można całkowicie uniknąć bezpośredniego pytania. Zwykle ludzie chcą wiedzieć, czy katalog jest pusty, ponieważ chcą zrobić coś z zawartymi w nim plikami itp. Spójrz na większe pytanie. Na przykład jeden z tych przykładów opartych na znajdowaniu może być odpowiednim rozwiązaniem:

   # Bourne
   find "$somedir" -type f -exec echo Found unexpected file {} \;
   find "$somedir" -maxdepth 0 -empty -exec echo {} is empty. \;  # GNU/BSD
   find "$somedir" -type d -empty -exec cp /my/configfile {} \;   # GNU/BSD

Najczęściej wszystko, czego naprawdę potrzeba, to coś takiego:

   # Bourne
   for f in ./*.mpg; do
        test -f "$f" || continue
        mympgviewer "$f"
    done

Innymi słowy, osoba zadająca pytanie mogła pomyśleć, że potrzebny jest jawny test pustego katalogu, aby uniknąć komunikatu o błędzie, takiego jak mympgviewer: ./*.mpg: Nie ma takiego pliku lub katalogu, podczas gdy w rzeczywistości taki test nie jest wymagany.


1

Mała odmiana odpowiedzi Bruno :

files=$(ls -1 /some/dir| wc -l)
if [ $files -gt 0 ] 
then
    echo "Contains files"
else
    echo "Empty"
fi

Mi to pasuje


1

Biorąc wskazówkę (lub kilka) z odpowiedzi Olibre, podoba mi się funkcja Bash:

function isEmptyDir {
  [ -d $1 -a -n "$( find $1 -prune -empty 2>/dev/null )" ]
}

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ć

if isEmptyDir somedir
then
  echo somedir is an empty directory
else
  echo somedir does not exist, is not a dir, is unreadable, or is  not empty
fi

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.


0

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:

ls -l <directory> | egrep -c "^-"

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:

 #!/bin/sh 
 fileNum=`ls -l <directory> | egrep -c "^-"`  
 if [ $fileNum == x ] 
 then  
 #do what you want to do
 fi

x to dowolna zmienna.


0

Mieszając suszone śliwki i ostatnie odpowiedzi, muszę

find "$some_dir" -prune -empty -type d | read && echo empty || echo "not empty"

działa to również w przypadku ścieżek ze spacjami



0

Poszedłbym na find:

if [ -z "$(find $dir -maxdepth 1 -type f)" ]; then
    echo "$dir has NO files"
else
    echo "$dir has files"

To sprawdza wynik wyszukiwania tylko plików w katalogu, bez przechodzenia przez podkatalogi. Następnie sprawdza wyjście używając -zopcji wziętej z man test:

   -z STRING
          the length of STRING is zero

Zobacz niektóre wyniki:

$ mkdir aaa
$ dir="aaa"

Pusty reż:

$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty

Po prostu dirs w tym:

$ mkdir aaa/bbb
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty

Plik w katalogu:

$ touch aaa/myfile
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
$ rm aaa/myfile 

Plik w podkatalogu:

$ touch aaa/bbb/another_file
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty

0

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"

#!/bin/bash
if ([ $(ls /some/dir | wc -l  | grep -w "0") ])
    then
        echo 'No files'
    else
        echo 'Found files'
fi

-1
if ls /some/dir/* >/dev/null 2>&1 ; then echo "huzzah"; fi;

Podoba mi się ten, ponieważ nie ma cudzysłowów ani nawiasów klamrowych.
Dave Webb,

Uważaj, aby nie używać tego, jeśli ustawisz nullglob, ponieważ wtedy lspolecenie się powiedzie.
Steve Kehlet

Nie będzie działać we wszystkich środowiskach, jeśli katalog zawiera pliki z kropkami.
Diego Augusto Molina

-1

aby przetestować określony katalog docelowy

if [ -d $target_dir ]; then
    ls_contents=$(ls -1 $target_dir | xargs); 
    if [ ! -z "$ls_contents" -a "$ls_contents" != "" ]; then
        echo "is not empty";
    else
        echo "is empty";
    fi;
else
    echo "directory does not exist";
fi;

-1

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

#!/bin/bash

_DIR="/home/user/test/"
#_DIR=$1
_FIND=$(find $_DIR -type f )
if [ -n "$_FIND" ]
then
   echo -e "$_DIR contains files or subdirs with files \n\n "
   echo "$_FIND"
else
echo "empty (or does not exist)"
fi

Jeśli katalog zawiera puste katalogi lub nieregularne pliki (gniazda, urządzenia znaków, dowiązania symboliczne itp.), To nie zadziała. Katalog zostałby zgłoszony jako pusty.
Diego Augusto Molina

@DiegoAugustoMolina, o ile dobrze zrozumiałem w pytaniu, to że szukamy czy pliki istnieją (jako pliki dosłownie) to dlatego użyto argumentu -f. ale twoje komentarze nadal są prawdziwe.
igiannak

-2

Nie podoba mi się ls - Azamieszczone 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ć ...

if !  rmdir ${target}
then
    echo "not empty"
else
    echo "empty"
    mkdir ${target}
fi

4
To nie działa, jeśli użytkownik nie ma uprawnień do zapisu ${target}/...
Jens,

To zły pomysł, żeby test był niszczycielski. Między innymi wprowadza warunki wyścigu.
manekiny

-2

U mnie dobrze to działa (gdy reż istnieje):

some_dir="/some/dir with whitespace & other characters/"
if find "`echo "$some_dir"`" -maxdepth 0 -empty | read v; then echo "Empty dir"; fi

Z pełną kontrolą:

if [ -d "$some_dir" ]; then
  if find "`echo "$some_dir"`" -maxdepth 0 -empty | read v; then echo "Empty dir"; else "Dir is NOT empty" fi
fi
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.