Boş dizinleri bulma UNIX


93

Belirli bir dizin listesi için boş dizinler bulmam gerekiyor. Bazı dizinlerin içinde dizinleri vardır.

İç dizinler de boşsa ana dizinin boş olduğunu, aksi takdirde boş olmadığını söyleyebilirim.

Bunu nasıl test edebilirim?

Örneğin:

A>A1(file1),A2 this is not empty beacuse of file1
B>B1(no file) this is empty
C>C1,C2 this is empty

2
Bence Martin'in cevabı burada en uygun olanı. Mevcut kabul edilen cevap yalnızca eksik bir sözde koddur.
Léo Léopold Hertz 준영

Yanıtlar:


34

find <dir> -type fHerhangi bir çıktı verip vermediğini kontrol edin . İşte bir örnek:

for dir in A B C; do
    [ -z "`find $dir -type f`" ] && echo "$dir is empty"
done

2
Hayır, alt dizinleri çıkarmaz. Bunun -type fiçin var.
Marcelo Cantos

Ancak boş dosyalar varsa çözümünüz mesajı vermez.
Yasir Arsanukaev

4
Yasir: İçinde boş bir dosya bulunan bir dizinin kendi içinde boş kalmayacağını düşünüyorum. Bu doğru sonuç olmaz mıydı?
Ukko

2
@akostadinov: OP'de belirtildiği gibi dizinleri ve dosyaları oluşturursam ve cevabımda mkdir A B C A/A1 A/A2 B/B1 C/C1 C/C2; touch A/A1/file1kodu çalıştırırsam, OP'nin gerektirdiği şekilde B ve C'nin boş olduğunu bildirir. Yani "işe yaramayacak" dan biraz daha spesifik olmanız gerekecek.
Marcelo Cantos

1
Benim gibi Bash noob iseniz, burada -z'nin ne anlama geldiğini kontrol edin .
OmarOthman

263

Bu biraz boş dizinlerle ne yapmak istediğinize bağlıdır. Bir ağaçtaki tüm boş dizinleri, örneğin dizinleri silmek istediğimde aşağıdaki komutu kullanıyorum test.

find test -depth -empty -delete

Yukarıdaki komutla ilgili dikkat edilmesi gereken bir nokta, boş dosyaları da kaldıracağıdır , bundan kaçınmak için -type d seçeneğini kullanın.

find test -depth -type d -empty -delete

-deleteEşleşen dosyaları ve dizinleri görmek için bırakın .

Boş dizin ağacına ilişkin tanımınız dosya içermemesidir, o zaman herhangi bir şey döndürüp find test -type fdöndürmediğine bağlı olarak bir şeyi birbirine yapıştırabilirsiniz .

find harika bir yardımcı programdır ve RTFM erken ve çoğu zaman ne kadar işe yaradığını gerçekten anlamak için :-)


8
-delete -depth anlamına gelir (en azından GNU findutils 4.4.2 için)
SO Stinks

4
bilmiyordum -empty, çok uygun!
Raffi

2
Ancak en son ve en büyük linux olmayan makinelerde. (EG Solaris), o zaman -boş veya -sil gibi süslü bulma özelliklerine sahip olmazsınız.
anthony

3
MacOS-X'te neredeyse boş dizinler için find test -name ".DS_Store" -deleteönce çalıştırın , ardından -empty deletekomutu çalıştırın . Ayrıca pushd, ana dizine benzer şekilde, öyle find testolur find ., ancak komutların geri kalanı aynıdır.
Olie

1
@Martin Lütfen tanımını -depthburaya ekleyebilir misiniz? Örneğin, derinlikli bir geçiş gerçekleştirmek için bul, yani, dizinler son sırayla ziyaret edilir ve bir dizindeki tüm girişler dizinin kendisinden önce hareket eder. Sanırım burayla alakalı.
Léo Léopold Hertz 준영

51

Aşağıdaki komutu kullanabilirsiniz:

find . -type d -empty

1
-empty yalnızca geçerli dizin tamamen boşsa çalışır, alt ağaç dosya içermiyorsa çalışmaz.
Marcelo Cantos

@soField Test edildi . FreeBSD ve CentOS ile d-boş . İyi çalışıyor. İşletim sisteminiz nedir?
mosg

1
hp-ux yani boş parametre yok
soField

@soField Gördüğünüz gibi, bu verileri sorunuzun
başına koymak

2
find, solaris üzerinde -empty'ye de sahip değildir, ancak derinlik ilk geçişi zorlamak için -depth değerine sahiptir, böylece boş alt dizinler, üst dizinin boş olup olmadığı kontrol edilmeden önce silinebilir.
eirikma

26
find directory -mindepth 1 -type d -empty -delete

Bu, en ilginç bulduğum versiyon. Dizinin içinden çalıştırılırsa, aşağıdaki tüm boş dizinleri siler (bir dizin yalnızca boş dizinler içeriyorsa boş kabul edilir).

Mindepth seçeneği, dizinin boş olması durumunda dizinin kendisinin silinmesini engeller.


2
rmdir --ignore-fail-on-non-empty -p directoryEbeveynlerden de kurtulmak için bunu takip edebilirsiniz .
Pete Peterson

@Pete Peterson Komutum, yalnızca diğer boş dizinleri içeren dizinleri kaldırıyor gibi görünüyor (bu, OP'nin de istediği şeydir). Komutunuzun, istediklerini gerçekleştirseler bile, kullanıcıyı genellikle eksik i-node'lu bir dizinde bırakacağını ve bu durumun kendileri için kafa karıştırıcı olabileceğini unutmayın. Belki de noktayı kaçırıyorum.
SO Stinks

23

find . -type d -empty

geçerli ağaçta boş dizinleri ve alt dizinleri bulur ve listeler. Örneğin, boş dizinlerin ve alt dizinlerin sonuç listesi:

./2047
./2032
./2049
./2063
./NRCP26LUCcct1/2039
./NRCP26LUCcct1/2054
./NRCP26LUCcct1/2075
./NRCP26LUCcct1/2070

Dizinler üzerinde herhangi bir işlem yapılmaz. Basitçe listelenirler. Bu benim için çalışıyor.


16

Sadece boş dizinler bulun

Sadece boş dizinler bulmak için (soru başlığında belirtildiği gibi), mosg'ın cevabı doğrudur:

find -type d -empty

Ancak -emptyçok eski findsürümlerde mevcut olmayabilir (örneğin bu HP-UX durumudur ). Durumunuz buysa, aşağıdaki Bir dizin boş mu? Bölümünde açıklanan tekniklere bakın. .

Boş dizinleri silin

Bu biraz karmaşık: Bir dizinin MyDirboş dizinler içerdiğini varsayalım . Bu boş dizinler kaldırıldıktan sonra boş bir dizin MyDirhaline gelecektir ve ayrıca kaldırılması gerekir. Bu nedenle , mümkün olduğunda ana dizinleri de kaldıran (veya ) rmdirseçeneğiyle komutu kullanıyorum :--parents-p

find -type d -empty -exec rmdir -vp --ignore-fail-on-non-empty {} +

Daha eski findsürümde ifade +henüz desteklenmemektedir, bu nedenle ;bunun yerine kullanabilirsiniz :

find -type d -empty -exec rmdir -vp --ignore-fail-on-non-empty {} `;`

Bir dizin boş mu?

Bu cevapların çoğu, bir dizinin boş olup olmadığının nasıl kontrol edileceğini açıklar. Bu nedenle burada bildiğim üç farklı tekniği sunuyorum:

  1. [ $(find your/dir -prune -empty) = your/dir ]

    d=your/dir
    if [ x$(find "$d" -prune -empty) = x"$d" ]
    then
      echo "empty (directory or file)"
    else
      echo "contains files (or does not exist)"
    fi
    

    bir varyasyon:

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

    Açıklama:

    • find -prunefind -maxdepth 0daha az karakter kullanmaya benzer
    • find -type d yalnızca dizinleri yazdırır
    • find -empty boş dizinleri ve dosyaları yazdırır

      > mkdir -v empty1 empty2 not_empty
      mkdir: created directory 'empty1'
      mkdir: created directory 'empty2'
      mkdir: created directory 'not_empty'
      > touch not_empty/file
      > find empty1 empty2 not_empty -prune -empty
      empty1
      empty2
      
  2. (( ${#files} ))

    Bu numara% 100'dür bashancak bir alt mermi çağırır (ortaya çıkarır). Fikir dan Bruno De Fraine ve geliştirilebilir teambob un yorumunu. Eğer kullanırsan bunu tavsiye ederim ve betiğinizin taşınabilir olması gerekmiyorsa.

    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 mevcut olmayan bir dizin arasında fark yoktur (ve sağlanan yol bir dosya olsa bile).

  3. [ $(ls -A your/dir) ]

    Bu numara nixCraft'ın 2007'de yayınlanan makalesinden esinlenmiştir . Andrew Taylor , 2008'de ve gr8can8dian'da 2011'de cevap verdi .

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

    veya tek satırlık bashizm versiyonu:

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

    Not: dizin olmadığında lsdöner $?=2. Ancak bir dosya ile boş bir dizin arasında hiçbir fark yoktur.


rmdir -vpBir kök altındaki tüm boş dizinleri silmem gerektiğinden, bir dosyayı sildikten sonra boş dizinleri ve ana dizinleri kontrol etmem gerektiğinden bana çok yardımcı oldu. Benim durumumda, şu anda bir dosyayı kaldırıyorum ağaçta olmadıkları sürece boş dizinler iyi durumda. Teşekkürler!
Ethan Hohensee

2

Bu özyinelemeli işlev hile yapıyor gibi görünüyor:

# Bash
findempty() {
    find ${1:-.} -mindepth 1 -maxdepth 1 -type d | while read -r dir
    do
        if [[ -z "$(find "$dir" -mindepth 1 -type f)" ]] >/dev/null
        then
            findempty "$dir"
            echo "$dir"
        fi
    done
}

Bu örnek dizin yapısı göz önüne alındığında:

    .
    | - dir1 /
    | - dir2 /
    | `- dirB /
    | - dir3 /
    | `- dirC /
    | `- dosya5
    | - dir4 /
    | | - dirD /
    | `- dosya4
    `- dir5 /
        `- dirE /
            `- dir_V /

Bu işlevi çalıştırmanın sonucu şu olur:

    ./dir1
    ./dir5/dirE/dir_V
    ./dir5/dirE
    ./dir5
    ./dir2/dirB
    ./dir2

hangi özlüyor /dir4/dirD. Eğer özyinelemeli çağrı taşırsanız findempty "$dir"sonrafi işlev sonuçlarına bu dizini dahil eder.


2

Nasıl olur rmdir *? Bu komut boş olmayan dizinlerde başarısız olacaktır.


Genel temizlik için zaman zaman yaptığım bir şey. Ayrıca rmdir */*/* */* * , 'nokta dosyalarını' işlememesine rağmen, ancak daha sonra manuel durumlarda (veri dosyalarını temizleme) genellikle 'nokta dosyaları' beklemeyin. Yinelemeli yöntemler, ancak, özellikle çok büyük dizin yapılarında, daha otomatikleştirilmiş genel temizlik içindir.
anthony

Tek bir "benioku" dosyası içerebilen "boş" dizinleri içeren boş dizinleri kaldırmam gerektiğinden, bir durumda daha karmaşıktı. Dizinde başka herhangi bir şey ve 'boş' değildi. Bu örnekte dizin yapısı on binlerce alt dizini içeriyordu.
anthony

1

Aşağıdaki komut, bir dizin boşsa (veya yoksa) 1 ve aksi takdirde 0 değerini döndürür (bu nedenle, dönüş kodunu !bir kabuk betiğinde ters çevirmek mümkündür ):

find $dir -type d -prune -empty -exec false {} +

0

Aşağıdaki gibi basit bir yapı oluşturdum:

test/
test/test2/
test/test2/test2.2/
test/test3/
test/test3/file

test/test3/fileBazı önemsiz metin içeriyor.

Yayınlama , tek boş dizin olarak find test -empty" test/test2/test2.2" döndürür .


operasyon test /

Aslında. Ama daha ileri gitmek için bul sayfasını okuyabileceğini düşündüm. Sonuçlara göre derinliği ayarlayan bir komut dosyası gayet iyi çalışır.
James Sumners

Bu, benim kullanımım için en kullanışlı versiyondu, teşekkürler
Andreas

0

basit bir yaklaşım,

$ [ "$(ls -A /path/to/direcory)" ] && echo "not empty" || echo "its empty"

Ayrıca,

if [ "$(ls -A /path/to/direcory)" ]; then
   echo "its not empty"
else 
   echo "empty directory"

0
find . -name -type d -ls |awk '($2==0){print $11}'
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.