Benim tldr cevabım:
function emptydir {
[ "$1/"* "" = "" ] 2> /dev/null &&
[ "$1/"..?* "" = "" ] 2> /dev/null &&
[ "$1/".[^.]* "" = "" ] 2> /dev/null ||
[ "$1/"* = "$1/*" ] 2> /dev/null && [ ! -e "$1/*" ] &&
[ "$1/".[^.]* = "$1/.[^.]*" ] 2> /dev/null && [ ! -e "$1/.[^.]*" ] &&
[ "$1/"..?* = "$1/..?*" ] 2> /dev/null && [ ! -e "$1/..?*" ]
}
POSIX uyumludur ve çok önemli olmadığı için, dizini listeleyen ve çıktıyı grep'e bağlayan çözümden genellikle daha hızlıdır.
Kullanımı:
if emptydir adir
then
echo "nothing found"
else
echo "not empty"
fi
Cevap gibi ben https://unix.stackexchange.com/a/202276/160204 ben yeniden yazmak,:
function emptydir {
! { ls -1qA "./$1/" | grep -q . ; }
}
Dizini listeler ve sonucu grep'e yönlendirir. Bunun yerine, glob genişlemesi ve karşılaştırmasına dayanan basit bir işlev öneriyorum.
function emptydir {
[ "$(shopt -s nullglob; echo "$1"/{,.[^.],..?}*)" = "" ]
}
Bu işlev standart POSIX değildir ve ile bir alt kabuk çağırır $(). Önce bu basit işlevi açıklarım, böylece nihai çözümü daha iyi anlayabiliriz (yukarıdaki tldr cevabına bakın).
Açıklama:
Genişletme olmadığında sol taraf (LHS) boştur; bu, dizin boş olduğunda geçerlidir. Nullglob seçeneği gereklidir, çünkü aksi takdirde eşleşme olmadığında globun kendisi genişlemenin sonucudur. (Bir LHS glob glob olarak adlandırılan tek bir dosyayla eşleştiğinde oluşan yanlış pozitifler nedeniyle dizin boş olduğunda RHS'nin LHS globlarıyla eşleşmesi çalışmaz: *glob *içindeki dosya dosya adındaki alt dizeyle eşleşir . ) Köşeli ayraç ifadesi {,.[^.],..?}gizli dosyaları kapsar, ancak ..veya içermez ..
Çünkü shopt -s nullglobidam içindedir $()(a altkabuk), bu değişmez nullglobnormalde iyi bir şeydir akım kabuk, seçeneği. Öte yandan, bu seçeneği komut dosyalarında ayarlamak iyi bir fikirdir, çünkü eşleşme olmadığında bir globun bir şey döndürmesi hatalıdır. Böylece, komut dosyasının başında nullglob seçeneği ayarlanabilir ve işlevde gerekli olmayacaktır. Bunu aklımda tutalım: nullglob seçeneğiyle çalışan bir çözüm istiyoruz.
Uyarılar:
Dizine okuma erişimimiz yoksa, işlev boş bir dizin varmış gibi raporlar. Bu, dizini listeleyen ve çıktıyı grep içeren bir işlev için de geçerlidir.
shopt -s nullglobKomut standart POSIX değildir.
Tarafından oluşturulan alt kabuğu kullanır $(). Bu büyük bir anlaşma değil, ama önleyebilirsek güzel.
Pro:
Gerçekten önemli değil, ancak bu işlev, işlem içindeki çekirdeğe harcanan CPU zamanı miktarı ile ölçülen öncekinden dört kat daha hızlıdır.
Diğer çözümler:
Biz olmayan POSIX kaldırabilirsiniz shopt -s nullgloblhs komuta ve dize koymak "$1/* $1/.[^.]* $1/..?*"RHS ve biz sadece adlandırılmış dosyaları olduğunda ayrı ayrı meydana yanlış pozitif ortadan kaldırmak '*', .[^.]*ya da ..?*dizinde:
function emptydir {
[ "$(echo "$1"/{,.[^.],..?}*)" = "$1/* $1/.[^.]* $1/..?*" ] &&
[ ! -e "$1/*" ] && [ ! -e "$1/.[^.]*" ] && [ ! -e "$1/..?*" ]
}
shopt -s nullglobKomut olmadan, alt kabuğu kaldırmak mantıklı, ancak dikkatli olmalıyız çünkü kelime bölünmesinden kaçınmak ve yine de LHS'de glob genişlemesine izin vermek istiyoruz. Özellikle kelime bölünmesini önlemek için alıntı yapmak işe yaramaz, çünkü aynı zamanda glob genişlemesini de önler. Çözümümüz globları ayrı ayrı düşünmektir:
function emptydir {
[ "$1/"* = "$1/*" ] 2> /dev/null && [ ! -e "$1/*" ] &&
[ "$1/".[^.]* = "$1/.[^.]*" ] 2> /dev/null && [ ! -e "$1/.[^.]*" ] &&
[ "$1/"..?* = "$1/..?*" ] 2> /dev/null && [ ! -e "$1/..?*" ]
}
Tek tek glob için hala kelime bölmemiz var, ama şimdi tamam, çünkü sadece dizin boş olmadığında bir hataya neden olacak. LHS'de verilen glob ile eşleşen birçok dosya olduğunda hata mesajını atmak için 2> / dev / null ekledik.
Nullglob seçeneğiyle de çalışan bir çözüm istediğimizi hatırlıyoruz. Yukarıdaki çözüm nullglob seçeneğiyle başarısız olur, çünkü dizin boş olduğunda, LHS'ler de boştur. Neyse ki, dizinin olmadığı zaman boş olduğunu asla söylemez. Sadece boşken boş olduğunu söyleyemez. Böylece, nullglob seçeneğini ayrı ayrı yönetebiliriz. Durumları [ "$1/"* = "" ]vb. Ekleyemeyiz çünkü bunlar [ = "" ]sözdizimsel olarak yanlış olan, vb. Bunun [ "$1/"* "" = "" ]yerine vs. kullanıyoruz. Biz yine üç kasa düşünmek zorundayız *, ..?*ve .[^.]*gizli dosyaları maç için değil, .ve... Nullglob seçeneğimiz yoksa bunlar karışmaz, çünkü aynı zamanda boş olmadığını da söylemezler. Yani, önerilen son çözüm:
function emptydir {
[ "$1/"* "" = "" ] 2> /dev/null &&
[ "$1/"..?* "" = "" ] 2> /dev/null &&
[ "$1/".[^.]* "" = "" ] 2> /dev/null ||
[ "$1/"* = "$1/*" ] 2> /dev/null && [ ! -e "$1/*" ] &&
[ "$1/".[^.]* = "$1/.[^.]*" ] 2> /dev/null && [ ! -e "$1/.[^.]*" ] &&
[ "$1/"..?* = "$1/..?*" ] 2> /dev/null && [ ! -e "$1/..?*" ]
}
Güvenlik endişesi:
Boş bir dizinde iki dosya oluşturun rmve bilgi isteminde xçalıştırın *. Glob *, genişleyecek rm xve çıkarmak için yürütülecektir x. Bu bir güvenlik kaygısı değildir, çünkü bizim fonksiyonumuzda globlar, genişlemelerin komut olarak değil, argümanlar olarak görüldüğü yerde bulunur for f in *.