it-swarm-tr.com

Bir dizinin dosya içerip içermediğini Shell kodundan kontrol etme

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

95
ionn

Ş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
61
Bruno De Fraine

En iyi üç numara


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 benzer
  • find -empty boş dizinleri ve dosyaları yazdırır
  • find -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 ...

128
olibre

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

47
mweerden

Deneyin:

if [ ! -z `ls /some/dir/*` ]; then echo "huzzah"; fi
19
Greg Hewgill
# 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
}
14
gr8can8dian

Ç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
12
Gravstar
DIR="/some/dir"
if [ "$(ls -A $DIR)" ]; then
     echo 'There is something alive in here'
fi
9
Andrew Taylor

Bunun çıktısını karşılaştırabilir misiniz?

 ls -A /some/dir | wc -l
5
DGM
 # 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.
  • Döngü içindeki 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ş" getirir
  • Bu fonksiyon tüm POSIX uygulamalarında çalışacaktır. Ancak Solaris/bin/sh'in bu kategoriye girmediğini unutmayın. test uygulaması, -e bayrağını desteklemez.
4
Roland Illig

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
3
Daishi

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
2
bitstreamer
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, bashdashposhbusybox 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 busyboxsh ü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).

1
Alex

ZSH

Sorunun bash için işaretlendiğini biliyorum; ancak, sadece referans için, zsh users için:

Boş olmayan dizini sınama

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.

Boş dizini test et

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.

Notlar

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.

Ekstralar

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

Açıklama

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

1
Zorawar

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.

1
ForDummies

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

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

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.

0
bishop

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
0
fedorqui

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
0
chanaka777

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

0
Jecht Tyre

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
0
GiannakopoulosJ

bash ile basit cevap:

if [[ $(ls /some/dir/) ]]; then echo "huzzah"; fi;
0
Thomas Steinbach

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

0
Laurent G