Bir Shell betiğinden, bir dizinin dosya içerip içermediğini nasıl kontrol ederim?
Buna benzer bir şey
if [ -e /some/dir/* ]; then echo "huzzah"; fi;
ancak, dizin bir veya birkaç dosya içeriyorsa işe yarar (yukarıdaki dosya yalnızca 0 veya 1 dosyayla çalışır).
Şimdiye kadarki çözümler ls
. İşte bir bash çözümü:
#!/bin/bash
shopt -s nullglob dotglob # To include hidden files
files=(/some/dir/*)
if [ ${#files[@]} -gt 0 ]; then echo "huzzah"; fi
shopt -s nullglob dotglob; f=your/dir/*; ((${#f}))
Bu numara% 100 bash
ve bir alt Shell çağırıyor (yumurtlar). Bu fikir Bruno De Fraine ve teambob 'nin yorumu ile geliştirildi.
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
Not: boş bir dizin ile var olmayan bir dizin arasında hiçbir fark yoktur (ve sağlanan yol bir dosya olduğunda bile).
#Bash FAQiçin 'resmi' IRC için benzer bir alternatif ve daha fazla ayrıntı (ve daha fazla örnek) var. _ kanal :
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)" ]
Bu numara, 2007'de yayınlanan nixCraft'ın makalesi 'den esinlenmiştir. Çıkış hatasını bastırmak için 2>/dev/null
ekleyin "No such file or directory"
.
Ayrıca bakınız Andrew Taylor Cevap (2008) ve gr8can8dian Cevap (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
ya da tek hat bashism versiyonu:
[[ $(ls -A your/dir) ]] && echo "contains files" || echo "empty"
Not: ls
, dizin bulunmadığında $?=2
değerini döndürür. Ancak bir dosya ile boş bir dizin arasında fark yoktur.
[ -n "$(find your/dir -Prune -empty)" ]
Bu son numara, gravstar'ın cevabı 'dan esinlenmiştir; burada -maxdepth 0
, -Prune
ile değiştirilir ve phils ' nin yorumu ile geliştirilir.
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
-type d
kullanarak bir varyasyon:
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
Açıklama:
find -Prune
, daha az karakter kullanarak find -maxdepth 0
öğesine benzerfind -empty
boş dizinleri ve dosyaları yazdırırfind -type d
yalnızca dizinleri yazdırır Not: [ -n "$(find your/dir -Prune -empty)" ]
işlevini aşağıdaki kısaltılmış sürümle de değiştirebilirsiniz:
if [ `find your/dir -Prune -empty 2>/dev/null` ]
then
echo "empty (directory or file)"
else
echo "contains files (or does not exist)"
fi
Bu son kod çoğu durumda çalışır, ancak kötü amaçlı yolların bir komut ifade edebileceğini unutmayın ...
Aşağıdakilere ne dersiniz:
if find /some/dir/ -maxdepth 0 -empty | read v; then echo "Empty dir"; fi
Bu şekilde dizinin içeriğinin tam bir listesini oluşturmaya gerek kalmaz. read
çıktısını atmak ve ifadeyi yalnızca bir şey okunduğunda doğru olarak değerlendirmesini sağlamak içindir (yani /some/dir/
find
tarafından boş bulunursa).
Deneyin:
if [ ! -z `ls /some/dir/*` ]; then echo "huzzah"; fi
# 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
}
Çok fazla dosya içeren dizinlere dikkat edin! ls
komutunu değerlendirmek biraz zaman alabilir.
IMO en iyi çözüm kullanandır
find /some/dir/ -maxdepth 0 -empty
DIR="/some/dir"
if [ "$(ls -A $DIR)" ]; then
echo 'There is something alive in here'
fi
Bunun çıktısını karşılaştırabilir misiniz?
ls -A /some/dir | wc -l
# Bir dizinin gizlenmemiş dosyalar içerip içermediğini kontrol eder . # # Use: isempty "$ HOME"; sonra yankı "Eve hoş geldin"; fi # isempty () { $ 1/* içindeki indirim için; yap eğer [-e "$ _ief"]; sonra 1 .__ döndür. fi yapılan dönüş 0 }
Bazı uygulama notları:
for
döngüsü, harici ls
işlemine yapılan çağrıyı engeller. Yine de bir kez tüm dizin girişlerini okur. Bu, yalnızca readdir () özelliğini kullanan bir C programı yazarak en iyi duruma getirilebilir.test -e
boş bir dizinin durumunu yakalar, bu durumda _ief
değişkenine "somedir/*" değeri atanır. Yalnızca bu dosya varsa, işlev "boş" getirirtest
uygulaması, -e
bayrağını desteklemez.Bu, dizinin boş olup olmadığını veya içermediği dosya sayısını gösterir.
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
Bu gerçekten geç bir cevap olabilir ama işte işe yarayan bir çözüm. Bu satır sadece th dosyalarının varlığını tanır! Dizinler varsa, size yanlış bir pozitif vermeyecektir.
if find /path/to/check/* -maxdepth 0 -type f | read
then echo "Files Exist"
fi
dir_is_empty() {
[ "${1##*/}" = "*" ]
}
if dir_is_empty /some/dir/* ; then
echo "huzzah"
fi
*
adında /any/dir/you/check
dosyasına sahip bir dosyanız olmadığını varsayalım, bash
dash
posh
busybox sh
ve zsh
üzerinde çalışmalıdır, ancak (zsh için) unsetopt nomatch
gerektirir.
Performanslar, *
(glob) kullanan herhangi bir ls
ile karşılaştırılabilir olmalıdır, sanırım birçok düğüm içeren dizinlerde yavaş olacak (3000+ dosya içeren /usr/bin
adresim yavaş değil), tüm dizinleri/dosya adlarını tahsis etmek için en az belleği kullanacak ve daha fazlası) hepsi argüman olarak işleve iletilir (çözülür), bazı Shell muhtemelen argüman sayısı ve/veya argüman uzunluğu konusunda bir sınırlamaya sahiptir.
Bir dizinin boş olup olmadığını kontrol etmek için portatif bir hızlı O(1) sıfır kaynak yolu olması güzel olurdu.
güncelleme
Yukarıdaki sürüm, Rich’in sh (POSIX Shell) hilelerinden : is_empty
gibi, daha fazla test yapılması gerekirse, gizli dosyaları/dizinleri hesaba katmaz.
is_empty () (
cd "$1"
set -- .[!.]* ; test -f "$1" && return 1
set -- ..?* ; test -f "$1" && return 1
set -- * ; test -f "$1" && return 1
return 0 )
Fakat bunun yerine böyle bir şeyi düşünüyorum:
dir_is_empty() {
[ "$(find "$1" -name "?*" | dd bs=$((${#1}+3)) count=1 2>/dev/null)" = "$1" ]
}
İzlemeyle ilgili bazı endişeler, dir boş olduğunda argüman ve bulma çıktısından farklılıkları keser ve izleyen yeni satırlar (ancak bunun işlenmesi kolay olmalıdır), ne yazık ki busybox
sh
üzerinde ne yazık ki, çıktı ile birlikte find -> dd
borusunda ne hata olduğunu göster rastgele kesildi (eğer cat
kullandıysam, çıktı hep aynı, dd
argümanı ile count
gibi görünüyor).
Sorunun bash için işaretlendiğini biliyorum; ancak, sadece referans için, zsh users için:
foo
dosyasının boş olup olmadığını kontrol etmek için:
$ for i in foo(NF) ; do ... ; done
foo
boş değilse, for
bloğundaki kod çalıştırılır.
foo
dosyasının boş olup olmadığını kontrol etmek için:
$ for i in foo(N/^F) ; do ... ; done
eğer foo
boşsa, for
bloğundaki kod çalıştırılır.
Yukarıdaki foo
dizinini alıntılamamız gerekmedi, ancak gerekirse şunları yapabiliriz:
$ for i in 'some directory!'(NF) ; do ... ; done
Ayrıca bir dizin olmasa bile birden fazla nesneyi test edebiliriz:
$ 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
Bir dizin olmayan her şey göz ardı edilir.
Kürelendiğimizden, herhangi bir glob (veya küme genişletme) kullanabiliriz:
$ 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
Bir diziye yerleştirilen nesneleri de inceleyebiliriz. Yukarıdaki gibi dizinlerle, örneğin:
$ 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
Böylece, zaten bir dizi parametresinde ayarlanmış olan nesneleri test edebiliriz.
for
bloğundaki kodun her dizinde sırayla çalıştırıldığını unutmayın. Bu istenmiyorsa, basitçe bir dizi parametresini doldurabilir ve sonra bu parametrede çalışabilirsiniz:
$ for i in *(NF) ; do full_directories+=($i) ; done
$ do_something $full_directories
Zsh kullanıcıları için, "full" (boş olmayan) dizinlerle eşleşen (F)
glob niteleyicisi (bkz. man zshexpn
) vardır:
$ 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/
Niteleyici (F)
eşleşen nesneleri listeler: bir dizindir VE boş değil. Bu nedenle, (^F)
eşleşiyor: bir dizin değil OR boş. Böylece, (^F)
tek başına örneğin normal dosyaları da listeler. Bu nedenle zshexp
man sayfasında açıklandığı gibi, yalnızca dizinleri listeleyen (/)
glob niteleyicisine de ihtiyacımız var:
$ 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
Böylece, belirli bir dizinin boş olup olmadığını kontrol etmek için aşağıdakileri çalıştırabilirsiniz:
$ mkdir X
$ for i in X(/^F) ; do echo $i ; done ; echo "finished"
X
finished
ve boş olmayan bir dizinin yakalanmayacağından emin olmak için:
$ mkdir Y
$ touch Y/.f
$ for i in Y(/^F) ; do echo $i ; done ; echo "finished"
zsh: no matches found: Y(/^F)
finished
Hata! Y
boş olmadığı için, zsh, (/^F)
("boş dizinler") için eşleşme bulamaz ve bu nedenle, dünyayla eşleşme bulunamadığını söyleyen bir hata mesajı gönderir. Bu nedenle, bu olası hata mesajlarını (N)
glob niteleyicisiyle bastırmamız gerekiyor:
$ mkdir Y
$ touch Y/.f
$ for i in Y(N/^F) ; do echo $i ; done ; echo "finished"
finished
Bu nedenle, boş olmayan dizinler için şu şekilde okuyabileceğiniz (N/^F)
niteleyicisine ihtiyacımız var: "beni hatalar, dolu olmayan dizinler hakkında uyarma".
Benzer şekilde, boş dizinler için aynı şekilde şöyle okuyabileceğimiz (NF)
niteleyicisine ihtiyacımız var: "beni başarısızlıklar, tam dizinler hakkında uyarma".
Olibre'nin cevabından bir ipucu (veya birkaçını) alarak Bash işlevini seviyorum:
function isEmptyDir {
[ -d $1 -a -n "$( find $1 -Prune -empty 2>/dev/null )" ]
}
Çünkü bir alt kabuk yaratırken, hayal edebileceğim ve bir isim vermek onu okunabilir kılan bir O(1) çözümüne yakındır. Sonra yazabilirim
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
O(1) için genel durumlar var: büyük bir dizinin silinmiş son giriş dışında tümü veya tümü varsa, "bulun" boş olup olmadığını belirlemek için her şeyi okumak zorunda kalabilir. Beklenen performansın O(1) olduğuna inanıyorum, ancak en kötü durum dizin boyutunda doğrusal. Bunu ölçmedim.
Bruno'nun cevabındaki küçük değişiklik :
files=$(ls -1 /some/dir| wc -l)
if [ $files -gt 0 ]
then
echo "Contains files"
else
echo "Empty"
fi
Benim için çalışıyor
if ls /some/dir/* >/dev/null 2>&1 ; then echo "huzzah"; fi;
Yünlü kılavuzda boş dizinler söz edilmedi şaşırdım. Bu rehber ve tüm yünler gerçekten Shell tipi sorular için mutlaka okunmalı.
Bu sayfanın notundan:
Asla çıktısını ayrıştırmaya çalışmayın. Ls -A çözümleri bile bozulabilir (örneğin, HP-UX’te, eğer kökseniz, ls -A yapar. bir şey inanılmaz derecede aptal).
Aslında, doğrudan bir sorudan tamamen kaçınmak isteyebilirsiniz. Genellikle insanlar a Dizin boştur çünkü oradaki dosyaları içeren bir şey yapmak istiyorlar, vb. soru. Örneğin, bu bulgu bazlı örneklerden biri uygun bir çözüm olabilir:
# 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
En çok, gerçekten gerekli olan şey şunun gibi bir şeydir:
# Bourne
for f in ./*.mpg; do
test -f "$f" || continue
mympgviewer "$f"
done
Başka bir deyişle, soruyu soran kişi açık bir boş dizin testinin .__ olduğunu düşünmüş olabilir. mympgviewer gibi bir hata iletisinden kaçınmak için gerekli: ./*.mpg: Aslında no böyle bir test gereklidir.
find
için giderim:
if [ -z "$(find $dir -maxdepth 1 -type f)" ]; then
echo "$dir has NO files"
else
echo "$dir has files"
Bu, alt dizinlerden geçmeden sadece dizindeki dosyaları arama çıkışını kontrol eder. Ardından çıktıyı -z
'dan alınan man test
seçeneğini kullanarak kontrol eder:
-z STRING
the length of STRING is zero
Bazı sonuçlara bakın:
$ mkdir aaa
$ dir="aaa"
Boş dir:
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty
Sadece içindeki pislikler:
$ mkdir aaa/bbb
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty
Dizindeki bir dosya:
$ touch aaa/myfile
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
$ rm aaa/myfile
Alt dizindeki bir dosya:
$ touch aaa/bbb/another_file
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty
Bazı geçici çözümlerde, bir dizinde dosya olup olmadığını bulmak için basit bir yol bulabilirim. Bu, özellikle .xml veya .txt dosyalarını vb. Kontrol etmek için grep komutlarıyla daha da genişletilebilir. Ör: 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
Şimdiye kadar daha basit bir cevap vereceğini düşündüğüm grep kullanan bir cevap görmedim (çok garip sembollerle değil!). İşte nasıl yaparım... Bourne Shell kullanarak dizinde herhangi bir dosya olup olmadığını kontrol edin:
bu, bir dizindeki dosya sayısını döndürür:
ls -l <directory> | egrep -c "^-"
dizinin yazıldığı yerdeki dizin yolunu doldurabilirsiniz. Borunun ilk yarısı, her bir dosya için ilk çıktı karakterinin "-" olmasını sağlar. egrep daha sonra düzenli ifadeler kullanarak o sembolüyle başlayan satır sayısını sayar. Şimdi tek yapmanız gereken, elde ettiğiniz sayıyı saklamak ve aşağıdaki gibi geri tırnak işaretleri kullanarak karşılaştırmaktır:
#!/bin/sh
fileNum=`ls -l <directory> | egrep -c "^-"`
if [ $fileNum == x ]
then
#do what you want to do
fi
x, seçtiğiniz bir değişkendir.
Command find ..__ komutunu deneyin .. Dizini sabit kodlanmış veya argüman olarak belirtin .. Ardından dizin içindeki tüm dosyaları aramaya başlayın.
#!/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
bash ile basit cevap:
if [[ $(ls /some/dir/) ]]; then echo "huzzah"; fi;
Kuru erik işleri ve son cevapları karıştırdım.
find "$some_dir" -Prune -empty -type d | read && echo empty || echo "not empty"
o da boşluklu yollar için çalışır