Hapus direktori induk (tidak kosong) jika direktori anak tertentu kosong

11

Saya harus menyimpan semua direktori yang berisi file dalam subdirektori tertentu tetapi untuk menghapus semua direktori di mana subdirektori kosong.

Untuk lebih spesifik di sini adalah struktur:

A
|
|--------312311
|       |
|       |----Recording
|       |----a.txt
|       |----b.txt
|
|
|--------453453
|       |----Recording
|                   |
|                   |-------a.mp3
|       |----a.txt
|       |----b.txt
|
|
|--------566532
|       |----Recording
|       |----a.txt
|       |----b.txt

Sub direktori mungkin atau mungkin tidak mengandung file. Jadi saya perlu menghapus seluruh direktori seperti '312311' & '566532' dan hanya '453453' harus dibiarkan dengan semua data di dalamnya karena memiliki file di folder 'Rekaman' yang merupakan direktori khusus untuk saya.

Saya melihat banyak posting tetapi tautan ke banyak nama file tertentu. Bantuan apa pun akan sangat dihargai karena saya perlu melakukannya berkali-kali dalam seminggu.

Derek James
sumber
Apakah Perekaman selalu ada di level pertama dalam direktori? Juga: apakah semua folder di tingkat pertama di dalam direktori utama?
Jacob Vlijm
A adalah direktori tingkat atas yang berisi direktori bernomor. Dan dalam direktori bernomor itu berisi folder 'Recording' serta beberapa file 'txt' seperti dalam contoh. Dan dalam 'Rekaman' itu mungkin atau mungkin tidak berisi file ..
Derek James
Apakah Anda akan menghapus gambar teks Anda dan menempatkan teks yang sebenarnya ke dalam pertanyaan Anda. Gambar teks rumit bagi kita untuk diproses. Menggunakan teks yang sebenarnya jauh lebih mudah, di antara kenyamanan bawaan lainnya.
LD James
saya melakukan hal yang sama seperti yang Anda minta James ..
Derek James

Jawaban:

12

Script di bawah ini akan melakukan persis seperti yang Anda gambarkan, yaitu:

  1. daftar folder di dalam direktori
  2. Lihat di dalam setiap folder untuk folder bernama "Perekaman"

    • Jika ada dan kosong, ia menghapus folder superiornya
    • jika tidak ada, ia juga menghapus folder superiornya
    • file di tingkat pertama di dalam A tidak akan dihapus.

Dalam sebuah gambar:

A
|
|--------123456
|       |
|       |----Recording
|       |----a.txt
|       |----b.txt
|
|
|--------635623
|       |----Recording
|                   |
|                   |-------a.mp3
|       |----a.txt
|       |----b.txt
|
|
|--------123456
|       |----Recording
|       |----a.txt
|       |----b.txt
|
|--------Monkey.txt

akan menghasilkan:

A
|
|
|--------635623
|       |----Recording
|                   |
|                   |-------a.mp3
|       |----a.txt
|       |----b.txt
|
|
|--------Monkey.txt

Naskah

#!/usr/bin/env python3
import os
import sys
import shutil

dr = sys.argv[1]

def path(*args):
    return os.path.join(*args)

for d in os.listdir(dr):
    try:
        if not os.listdir(path(dr, d, "Recording")):
            shutil.rmtree(path(dr,d))
    except FileNotFoundError:
        shutil.rmtree(path(dr,d))
    except NotADirectoryError:
        pass

Menggunakan

  1. Salin skrip ke file kosong, simpan sebagai delete_empty.py
  2. Jalankan dengan direktori (penuh!) (Berisi dalam subdir Anda, A dalam contoh Anda) sebagai argumen dengan perintah:

    python3 /path/to/delete_empty.py /path/to/directory
    

Itu dia.

Penjelasan

Mengumpankan konten folder Anda "A" ke skrip,

os.listdir(dr)

akan mendaftar subdirektori (dan file). Kemudian:

if not os.listdir(path(dr, d, "Recording"))

akan mencoba membuat daftar konten dari masing-masing folder (sub), yang akan menimbulkan kesalahan jika item tersebut adalah file:

except NotADirectoryError
    pass

atau jika folder "Rekaman" tidak ada sama sekali:

FileNotFoundError
    shutil.rmtree(path(dr,d))

Jika folder "Rekaman" ada dan kosong, folder superior dihapus:

if not os.listdir(path(dr, d, "Recording")):
    shutil.rmtree(path(dr,d))

EDIT

Selain itu, seperti yang diminta dalam komentar, versi yang akan memeriksa beberapa subdir (nama).

Jika direktori berisi salah satu dari subdir yang terdaftar (kosong), direktori tersebut disimpan. Jika tidak maka akan dihapus.

Menggunakan

  1. Salin skrip ke file kosong, simpan sebagai delete_empty.py
  2. Jalankan dengan direktori (penuh!) (Berisi subdir Anda, A dalam contoh Anda) dan nama-nama subdirs sebagai argumen dengan perintah:

    python3 /path/to/delete_empty.py /path/to/directory <subdir1> <subdir2> <subdir3>
    

Itu dia.

Naskah

#!/usr/bin/env python3
import shutil
import os
import sys

dr = sys.argv[1]; matches = sys.argv[2:]

def path(*args):
    return os.path.join(*args)

for d in os.listdir(dr):
    # delete directory *unless* either one of the listed subdirs has files
    keep = False
    # check for each of the listed subdirs(names)
    for name in matches:
        try:
            if os.listdir(path(dr, d, name)):
                keep = True
                break
        except NotADirectoryError:
            # if the item is not a dir, no use for other names to check
            keep = True
            break
        except FileNotFoundError:
            # if the name (subdir) does not exist, check for the next
            pass
    if not keep:
        # if there is no reason to keep --> delete
        shutil.rmtree(path(dr,d))

Catatan

Pertama jalankan di direktori tes untuk memastikan itu melakukan apa yang Anda inginkan.

Yakub Vlijm
sumber
kode ini sangat membantu dan berfungsi seperti yang dikatakan. Terima kasih untuk kodenya. Sangat membantu.
Derek James
Misalkan jika saya perlu menyimpan dan memeriksa dua folder atau lebih, bagaimana saya dapat melakukannya dalam kode ini? menambahkan 'ATAU' atau pipa '| 'di suatu tempat .. sarankan sumthing!
Derek James
Hai @DerekJames yang hanya memerlukan suntingan kecil, saya akan memposting sore ini.
Jacob Vlijm
@ Serek, tunggu, haruskah folder superior dihapus jika ada folder yang kosong, atau semuanya? Mungkinkah ada banyak dari mereka dalam satu dir superior?
Jacob Vlijm
Misalkan @Jacob, saya punya dua folder 'Merekam' Dan 'Video'. Itu harus memeriksa keduanya. Jika salah satu dari subfolder berisi file, folder '635623' seharusnya tidak dihapus. Dan juga kemampuan untuk menambahkan lebih banyak folder untuk memeriksa apakah itu dapat dilakukan ..
Derek James
11

Menggunakan finddan xargs:

find A -type d -name 'Recording' -empty -printf '%h\0' | xargs -0 echo rm -rf

(hapus echobegitu Anda merasa nyaman bahwa itu mengidentifikasi direktori yang benar). Bagian printf '%h\0mencetak direktori induk (null dihentikan) - dari man find:

       %h     Leading directories of file's name (all but the last ele‐
              ment).  If the file name contains no slashes (since it is
              in  the  current  directory)  the %h specifier expands to
              ".".

Mis .: diberikan

$ tree A
A
├── 312311
│   ├── a.txt
│   ├── b.txt
│   └── Recording
├── 453453
│   ├── a.txt
│   ├── b.txt
│   └── Recording
│       └── a.mp3
└── 566532
    ├── a.txt
    ├── b.txt
    └── Recording

6 directories, 7 files

kemudian

$ find A -type d -name 'Recording' -empty -printf '%h\0' | xargs -0 rm -rf
$ 
$ tree A
A
└── 453453
    ├── a.txt
    ├── b.txt
    └── Recording
        └── a.mp3

2 directories, 3 files
Steeldriver
sumber
temukan A -type d -name 'Rekaman' -empty -printf '% h \ 0' | xargs -0 echo rm -rf ini hanya mencetak "rm -rf" DAN temukan A -type d -name 'Rekaman' -empty -printf '% h \ 0' | xargs -0 rm -rf tidak berfungsi ... Apakah saya melakukan sesuatu yang salah ..
Derek James
@DerekJames Anda harus mengganti A dengan direktori yang sebenarnya.
Jacob Vlijm
Apakah boleh menempatkan ekspresi reguler sebagai ganti nama Rekaman karena OP memberi nama file dengan angka, katakan [\d]*?
George Udosen
@JacobVlijm: Saya diganti dengan direktori aktual tetapi masih belum menulis?
Derek James
@DerekJames itu aneh! ini bekerja pada sistem saya, tetapi Anda mungkin lupa untuk cd ke direktori terlebih dahulu? Tunggu, itu seharusnya tidak masalah ...
Jacob Vlijm
3

Berikut ini adalah solusi bash yang lebih sederhana:

for d in */; do rmdir "$d/Recording" && rm -r "$d"; done

Ini berfungsi karena rmdirakan gagal jika direktori tidak kosong, dan &&akan mencegah rm -rdari dieksekusi kecuali rmdirberhasil. Glob */memastikan Anda hanya bekerja pada direktori, jadi file lain tidak akan terpengaruh.

JoL
sumber
Berpikir cerdas! +1
Jacob Vlijm