Xóa thư mục mẹ (không trống) nếu một thư mục con cụ thể trống


11

Tôi phải giữ tất cả các thư mục chứa các tệp trong một thư mục con cụ thể nhưng để xóa tất cả các thư mục trong đó thư mục con trống.

Cụ thể hơn ở đây là cấu trúc:

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

Các thư mục con có thể có hoặc không chứa tệp. Vì vậy, tôi cần xóa toàn bộ thư mục như '312311' & '566532' và chỉ còn lại '453453' với tất cả dữ liệu trong đó vì nó có một tệp trong thư mục 'Ghi âm' là thư mục cụ thể cho tôi.

Tôi thấy nhiều bài viết nhưng nó liên kết đến nhiều tên tập tin cụ thể. Bất kỳ trợ giúp sẽ được đánh giá cao vì tôi cần phải làm nhiều lần trong một tuần.


Ghi âm luôn ở cấp độ đầu tiên trong thư mục? Ngoài ra: tất cả các thư mục ở cấp độ đầu tiên bên trong thư mục chính?
Jacob Vlijm

A là thư mục cấp cao nhất trong đó nó chứa các thư mục được đánh số. Và trong các thư mục được đánh số, nó chứa thư mục 'Ghi âm' cũng như một số tệp 'txt' như trong ví dụ. Và trong 'Ghi âm', nó có thể có hoặc không chứa các tệp ..
Derek James

Bạn sẽ loại bỏ hình ảnh của văn bản của bạn và đặt văn bản thực tế vào câu hỏi của bạn. Hình ảnh của văn bản là cồng kềnh để chúng tôi xử lý. Sử dụng văn bản thực tế là thuận tiện hơn đáng kể, trong số các tiện ích vốn có khác.
LD James

tôi cũng làm như vậy với bạn James ..
Derek James

Câu trả lời:


12

Kịch bản dưới đây sẽ làm chính xác như bạn mô tả, nó:

  1. liệt kê các thư mục trong một thư mục
  2. Nhìn vào bên trong mỗi thư mục cho một thư mục có tên "Ghi âm"

    • Nếu nó tồn tại trống, nó sẽ xóa thư mục ưu việt của nó
    • nếu nó không tồn tại, nó cũng xóa thư mục cao cấp của nó
    • các tệp ở cấp độ đầu tiên bên trong A sẽ không bị xóa.

Trong một hình ảnh:

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

sẽ cho kết quả:

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

Kịch bản

#!/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

Để sử dụng

  1. Sao chép tập lệnh vào một tập tin trống, lưu nó dưới dạng delete_empty.py
  2. Chạy nó với thư mục (full!) (Chứa các thư mục con của bạn, A trong ví dụ của bạn) làm đối số bằng lệnh:

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

Đó là nó.

Giải trình

Cung cấp nội dung của thư mục "A" cho tập lệnh,

os.listdir(dr)

sẽ liệt kê các thư mục con của nó (và các tệp). Sau đó:

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

sẽ cố gắng liệt kê nội dung của từng thư mục (phụ), điều này sẽ gây ra lỗi nếu mục đó là một tệp:

except NotADirectoryError
    pass

hoặc nếu thư mục "Ghi âm" hoàn toàn không tồn tại:

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

Nếu thư mục "Ghi âm" tồn tại trống, thư mục ưu việt sẽ bị xóa:

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

BIÊN TẬP

Ngoài ra, như được yêu cầu trong các nhận xét, một phiên bản sẽ kiểm tra nhiều thư mục con (tên).

Trong trường hợp thư mục chứa bất kỳ thư mục con nào được liệt kê (không trống), thư mục sẽ được giữ. Khác nó sẽ bị xóa.

Để sử dụng

  1. Sao chép tập lệnh vào một tập tin trống, lưu nó dưới dạng delete_empty.py
  2. Chạy nó với thư mục (full!) (Có chứa các thư mục con của bạn, A trong ví dụ của bạn) và tên của các thư mục con dưới dạng đối số của lệnh:

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

Đó là nó.

Kịch bản

#!/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))

Ghi chú

Trước tiên hãy chạy trên một thư mục thử nghiệm để đảm bảo nó thực hiện chính xác những gì bạn muốn.


mã này thực sự có ích và nó hoạt động như đã nói. Cảm ơn mã. Thực sự hữu ích.
Derek James

Giả sử nếu tôi cần giữ và kiểm tra hai thư mục trở lên, làm thế nào tôi có thể làm được trong mã này? thêm 'HOẶC' hoặc ống '| 'ở đâu đó .. đề nghị sum sum!
Derek James

Xin chào @DerekJames chỉ cần một chỉnh sửa nhỏ, tôi sẽ đăng vào chiều nay.
Jacob Vlijm

@Derek, đợi đã, thư mục ưu việt có nên bị xóa nếu có bất kỳ thư mục nào trống không, hay tất cả? Có thể có nhiều người trong số họ trong một thư mục cao cấp?
Jacob Vlijm

Giả sử @Jacob, tôi có hai thư mục 'Ghi âm' và 'Video'. Nó nên kiểm tra cả hai. Nếu bất kỳ thư mục con nào chứa tệp, thư mục '635623' sẽ không bị xóa. Và cũng có khả năng thêm nhiều thư mục để kiểm tra nếu nó có thể được thực hiện ..
Derek James

11

Sử dụng findxargs:

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

(loại bỏ echomột khi bạn cảm thấy thoải mái khi xác định đúng thư mục). Phần này printf '%h\0in thư mục mẹ (null chấm dứt) - từ 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
              ".".

Vd: đã cho

$ 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

sau đó

$ 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

tìm A -type d -name 'Ghi âm' -empty -printf '% h \ 0' | xargs -0 echo rm -rf đây chỉ là in "rm -rf" VÀ tìm A -type d -name 'Record' -empty -printf '% h \ 0' | xargs -0 rm -rf không hoạt động ... Tôi có làm gì sai không ..
Derek James

@DerekJames bạn cần thay thế A bằng thư mục thực tế.
Jacob Vlijm

Bạn có thể đặt một biểu thức thông thường thay cho tên Ghi âm vì OP đã đặt tên tệp với các số [\d]*không?
George Udosen

@JacobVlijm: Tôi đã thay thế bằng thư mục thực tế nhưng vẫn không vặn vẹo?
Derek James

@DerekJames thật kỳ quặc! nó hoạt động trên hệ thống của tôi, nhưng bạn có thể đã quên cd vào thư mục trước? Chờ đợi, điều đó không thành vấn đề ...
Jacob Vlijm 18/03/17

3

Đây là một giải pháp bash đơn giản hơn:

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

Nó hoạt động vì rmdirsẽ thất bại nếu thư mục không trống và &&sẽ ngăn không cho rm -rthực thi trừ khi rmdirthành công. Toàn cầu */đảm bảo bạn chỉ làm việc trên các thư mục, vì vậy các tệp khác sẽ không bị ảnh hưởng.


Suy nghĩ thông minh! +1
Jacob Vlijm
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.