Menemukan direktori kosong UNIX

92

Saya perlu mencari direktori kosong untuk daftar direktori tertentu. Beberapa direktori memiliki direktori di dalamnya.

Jika di dalam direktori juga kosong, saya dapat mengatakan direktori utama kosong jika tidak, tidak kosong.

Bagaimana saya bisa menguji ini?

Sebagai contoh:

A>A1(file1),A2 this is not empty beacuse of file1
B>B1(no file) this is empty
C>C1,C2 this is empty
soField
sumber
2
Saya rasa jawaban Martin paling tepat di sini. Jawaban yang diterima saat ini hanyalah pseudocode yang tidak lengkap.
Léo Léopold Hertz 준영

Jawaban:

34

Periksa apakah find <dir> -type fmenghasilkan sesuatu. Berikut contohnya:

for dir in A B C; do
    [ -z "`find $dir -type f`" ] && echo "$dir is empty"
done
Marcelo Cantos
sumber
2
Tidak, ini tidak akan menampilkan subdirektori. Itulah gunanya -type f.
Marcelo Cantos
Namun jika ada file kosong , solusi Anda tidak akan menghasilkan pesan.
Yasir Arsanukaev
4
Yasir: Menurut saya direktori yang berisi file kosong tidak boleh kosong sendiri. Bukankah itu hasil yang benar?
Ukko
2
@akostadinov: Jika saya membuat direktori dan file seperti yang ditunjukkan oleh OP - mkdir A B C A/A1 A/A2 B/B1 C/C1 C/C2; touch A/A1/file1- dan menjalankan kode dalam jawaban saya, ia melaporkan bahwa B dan C kosong, seperti yang diminta oleh OP. Jadi, Anda harus sedikit lebih spesifik daripada, "itu tidak akan berhasil".
Marcelo Cantos
1
Jika Anda seorang Bash noob seperti saya, periksa apa artinya -z di sini .
OmarOthman
261

Itu sedikit tergantung pada apa yang ingin Anda lakukan dengan direktori kosong. Saya menggunakan perintah di bawah ini ketika saya ingin menghapus semua direktori kosong di dalam pohon, katakanlah testdirektori.

find test -depth -empty -delete

Satu hal yang perlu diperhatikan tentang perintah di atas adalah perintah tersebut juga akan menghapus file kosong , jadi gunakan opsi -type d untuk menghindarinya.

find test -depth -type d -empty -delete

Lepaskan -deleteuntuk melihat file dan direktori yang cocok.

Jika definisi Anda tentang pohon direktori kosong adalah tidak berisi file, maka Anda dapat menyatukan sesuatu berdasarkan apakah find test -type fmengembalikan sesuatu.

find adalah utilitas yang hebat, dan RTFM lebih awal dan sering untuk benar-benar memahami seberapa banyak yang dapat dilakukannya :-)

Martin
sumber
8
-hapus menyiratkan -depth (setidaknya untuk GNU findutils 4.4.2)
Dr. Person Person II
4
tidak tahu tentang -empty, sangat nyaman!
Raffi
2
Namun pada mesin yang bukan linux terbaru dan terhebat. (Misalnya Solaris), maka Anda tidak perlu menemukan fitur-fitur mewah seperti -empty atau -delete.
anthony
3
Di MacOS-X, untuk direktori yang hampir kosong, jalankan find test -name ".DS_Store" -deletedulu, lalu -empty deleteperintah. Perhatikan juga, suka ke pushddirektori induk, sehingga find testmenjadi find ., tetapi perintah lainnya sama.
Olie
1
@Martin Bisakah Anda menambahkan definisi di -depthsini yaitu Penyebab find untuk melakukan traversal kedalaman pertama, yaitu direktori dikunjungi dalam urutan pasca dan semua entri dalam direktori akan dijalankan sebelum direktori itu sendiri. Saya pikir itu relevan di sini.
Léo Léopold Hertz 준영
50

Anda dapat menggunakan perintah berikut:

find . -type d -empty
mosg
sumber
1
-empty hanya berfungsi jika direktori saat ini benar-benar kosong, tidak jika subtree tidak berisi file.
Marcelo Cantos
@soField Tested temukan. -type d -empty dengan FreeBSD & CentOS. Bekerja dengan baik. Apa OS Anda?
mosg
1
hp-ux jadi tidak ada parameter kosong
soField
@soField Jadi, Anda lihat, bahwa lebih baik (bagi kita semua) untuk memposting data ini di bagian atas pertanyaan Anda ...
mosg
2
find juga tidak memiliki -empty pada solaris, tetapi memiliki -depth untuk menjalankan depth-first traversal sehingga subdirektori kosong dapat dihapus sebelum direktori induk diperiksa kekosongannya.
eirikma
26
find directory -mindepth 1 -type d -empty -delete

Ini adalah versi yang menurut saya paling menarik. Jika dijalankan dari dalam direktori , maka akan menghapus semua direktori kosong di bawah ini (direktori dianggap kosong jika hanya berisi direktori kosong).

Opsi mindepth mencegah direktori itu sendiri dihapus jika ternyata kosong.

Dr. Orang Orang II
sumber
2
Anda dapat menindaklanjutinya dengan rmdir --ignore-fail-on-non-empty -p directorymenyingkirkan orang tua juga.
Pete Peterson
@ Peterson @ Peterson Perintah saya tampaknya menghapus direktori yang hanya berisi direktori kosong lainnya (yang tampaknya juga diinginkan OP). Saya perhatikan bahwa perintah Anda biasanya akan meninggalkan pengguna di direktori dengan i-node yang hilang bahkan jika mereka mencapai apa yang mereka inginkan, yang mungkin membingungkan mereka. Mungkin aku melewatkan intinya.
Dr. Person Person II
23

find . -type d -empty

menemukan dan mencantumkan direktori dan sub-direktori kosong di pohon saat ini. Misalnya daftar yang dihasilkan dari dirs dan subdir yang kosong:

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

Tidak ada operasi yang dilakukan pada direktori. Mereka hanya terdaftar. Ini berhasil untuk saya.

user7194913
sumber
16

Temukan saja dirs kosong

Untuk menemukan direktori kosong (seperti yang ditentukan dalam judul pertanyaan), jawaban mosg benar:

find -type d -empty

Tetapi -emptymungkin tidak tersedia pada findversi yang sangat lama (ini adalah kasus HP-UX misalnya). Jika ini kasus Anda, lihat teknik yang dijelaskan di bagian di bawah ini Apakah direktori kosong? .

Hapus direktori kosong

Ini agak rumit: Misalkan sebuah direktori MyDirberisi direktori kosong. Setelah menghapus direktori kosong tersebut, MyDirakan menjadi direktori kosong dan juga harus dihapus. Oleh karena itu saya menggunakan perintah rmdirdengan opsi --parents(atau -p) yang juga menghapus direktori induk bila memungkinkan:

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

Pada findversi yang lebih lama , pernyataan +tersebut belum didukung, oleh karena itu Anda dapat menggunakan ;:

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

Apakah direktori kosong?

Sebagian besar jawaban ini menjelaskan cara memeriksa apakah direktori kosong. Oleh karena itu saya berikan di sini tiga teknik berbeda yang saya ketahui:

  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
    

    variasi:

    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
    

    Penjelasan:

    • find -prunemirip find -maxdepth 0dengan menggunakan lebih sedikit karakter
    • find -type d mencetak direktori saja
    • find -empty mencetak direktori dan file kosong

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

    Trik ini 100% bashtetapi memanggil (memunculkan) sub-shell. Ide ini dari Bruno De Fraine dan ditingkatkan dengan komentar teambob . Saya menyarankan yang ini jika Anda menggunakan dan jika script Anda tidak harus portabel.

    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
    

    catatan: tidak ada perbedaan antara direktori kosong dan yang tidak ada (dan bahkan jika jalur yang diberikan adalah file).

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

    Trik ini terinspirasi dari artikel nixCraft yang diposting pada tahun 2007. Andrew Taylor menjawab pada 2008 dan gr8can8dian pada 2011.

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

    atau versi bashism satu baris:

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

    Catatan: ls kembali $?=2jika direktori tidak ada. Tetapi tidak ada perbedaan antara file dan direktori kosong.

oHo
sumber
rmdir -vpsangat membantu saya karena saya tidak hanya perlu menghapus semua direktori kosong di bawah root, tetapi juga memeriksa direktori kosong dan direktori induk setelah menghapus file. Dalam situasi saya dirs kosong baik-baik saja selama mereka tidak ada di pohon tempat saya saat ini menghapus file. Terima kasih!
Ethan Hohensee
2

Fungsi rekursif ini sepertinya berhasil:

# 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
}

Diberikan contoh struktur direktori ini:

    .
    | - dir1 /
    | - dir2 /
    | `- dirB /
    | - dir3 /
    | `- dirC /
    | `- file5
    | - dir4 /
    | | - dirD /
    | `- file4
    `- dir5 /
        `- dirE /
            `- dir_V /

Hasil dari menjalankan fungsi itu adalah:

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

yang meleset /dir4/dirD. Jika Anda memindahkan panggilan rekursif findempty "$dir"setelah fi, fungsi tersebut akan menyertakan direktori tersebut dalam hasilnya.

Dijeda sampai pemberitahuan lebih lanjut.
sumber
2

Bagaimana dengan rmdir *? Perintah itu akan gagal pada direktori yang tidak kosong.

evandrix
sumber
Sesuatu yang pernah saya lakukan, untuk pembersihan umum. Juga melakukan hal-hal seperti rmdir */*/* */* * Meskipun itu tidak menangani 'file-dot' tetapi kemudian dalam situasi manual (membersihkan file data) Anda biasanya tidak mengharapkan 'file-dot'. Metode rekursif, bagaimanapun, adalah untuk pembersihan umum yang lebih otomatis, terutama dalam struktur direktori yang sangat besar.
anthony
Dalam satu kasus lebih rumit karena saya perlu menghapus direktori kosong di mana 'kosong' termasuk direktori yang dapat berisi satu file 'readme'. Ada yang lain di direktori dan tidak 'kosong'. Dalam contoh itu, struktur direktori melibatkan puluhan ribu sub-direktori.
anthony
1

Perintah berikut mengembalikan 1 jika direktori kosong (atau tidak ada) dan 0 sebaliknya (sehingga dimungkinkan untuk membalikkan kode pengembalian dengan !skrip shell):

find $dir -type d -prune -empty -exec false {} +
Mateusz Piotrowski
sumber
0

Saya membuat struktur sederhana sebagai berikut:

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

The test/test3/fileberisi beberapa teks sampah.

Menerbitkan find test -emptymengembalikan " test/test2/test2.2" sebagai satu-satunya direktori kosong.

James Sumners
sumber
op meminta test / test2 untuk dikembalikan juga
Memang. Tapi kupikir dia bisa membaca halaman manual find untuk melangkah lebih jauh. Skrip yang menyesuaikan kedalaman berdasarkan hasil akan berfungsi dengan baik.
James Sumners
Ini adalah versi yang paling berguna untuk saya gunakan, terima kasih
Andreas
0

pendekatan sederhana adalah,

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

juga,

if [ "$(ls -A /path/to/direcory)" ]; then
   echo "its not empty"
else 
   echo "empty directory"
phoenix24
sumber
0
find . -name -type d -ls |awk '($2==0){print $11}'
Vijay
sumber