Tìm thư mục trống UNIX


91

Tôi cần tìm các thư mục trống cho một danh sách các thư mục nhất định. Một số thư mục có các thư mục bên trong nó.

Nếu các thư mục bên trong cũng trống, tôi có thể nói thư mục chính trống nếu không thì nó không trống.

Làm thế nào tôi có thể kiểm tra điều này?

Ví dụ:

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
Tôi nghĩ câu trả lời của Martin là thích hợp nhất ở đây. Câu trả lời được chấp nhận hiện tại chỉ là một mã giả không hoàn chỉnh.
Léo Léopold Hertz 준영

Câu trả lời:


34

Kiểm tra xem find <dir> -type fđầu ra có gì không. Đây là một ví dụ:

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

2
Không, nó sẽ không xuất ra các thư mục con. Đó là những gì -type flà cho.
Marcelo Cantos

Tuy nhiên, nếu có tệp trống , giải pháp của bạn sẽ không mang lại thông báo.
Yasir Arsanukaev

3
Yasir: Tôi sẽ nghĩ rằng một thư mục chứa một tập tin trống không tự nó trống. Đó sẽ không phải là kết quả chính xác?
Ukko

2
@akostadinov: Nếu tôi tạo các thư mục và tệp theo chỉ định của OP - mkdir A B C A/A1 A/A2 B/B1 C/C1 C/C2; touch A/A1/file1- và chạy mã trong câu trả lời của tôi, nó sẽ báo rằng B và C trống, theo yêu cầu của OP. Vì vậy, bạn sẽ cần phải cụ thể hơn một chút so với "nó sẽ không hoạt động".
Marcelo Cantos

1
Nếu bạn là một Bash noob như tôi, hãy kiểm tra -z có nghĩa là gì ở đây .
OmarOthman

257

Nó phụ thuộc một chút vào những gì bạn muốn làm với các thư mục trống. Tôi sử dụng lệnh dưới đây khi tôi muốn xóa tất cả các thư mục trống trong một cây, chẳng hạn như testthư mục.

find test -depth -empty -delete

Một điều cần lưu ý về lệnh trên là nó cũng sẽ xóa các tệp trống , vì vậy hãy sử dụng tùy chọn -type d để tránh điều đó.

find test -depth -type d -empty -delete

Thả -deleteđể xem các tệp và thư mục phù hợp.

Nếu định nghĩa của bạn về cây thư mục trống là nó không chứa tệp nào thì bạn có thể gắn một thứ gì đó lại với nhau dựa trên việc có find test -type ftrả về bất kỳ thứ gì hay không.

find là một tiện ích tuyệt vời và RTFM sớm và thường xuyên để thực sự hiểu nó có thể làm được bao nhiêu :-)


8
-delete ngụ ý chiều sâu (ít nhất là cho GNU findutils 4.4.2)
Tiến sĩ Person Người II

4
không biết về -empty, rất thuận tiện!
Raffi

2
Tuy nhiên trên máy không phải là linux mới nhất và tốt nhất. (EG Solaris), thì bạn không có các tính năng tìm kiếm ưa thích như -empty hoặc -delete.
anthony

3
Trên MacOS-X, đối với các thư mục gần như trống, hãy chạy find test -name ".DS_Store" -deletetrước, sau đó chạy -empty deletelệnh. Cũng lưu ý, giống như pushdthư mục mẹ, để find testtrở thành find ., nhưng phần còn lại của các lệnh đều giống nhau.
Olie

1
@Martin Bạn có thể vui lòng thêm định nghĩa của -depthở đây, tức là Tìm nguyên nhân để thực hiện chuyển tải theo chiều sâu, tức là, các thư mục được truy cập theo thứ tự sau và tất cả các mục trong một thư mục sẽ hoạt động trước chính thư mục đó. Tôi nghĩ rằng nó có liên quan ở đây.
Léo Léopold Hertz 준영

49

Bạn có thể sử dụng lệnh sau:

find . -type d -empty

1
-empty chỉ hoạt động nếu thư mục hiện tại hoàn toàn trống, không nếu cây con không chứa tệp.
Marcelo Cantos

@soField Tìm thấy đã kiểm tra . -type d -empty với FreeBSD & CentOS. Hoạt động tốt. Hệ điều hành của bạn là gì?
mosg

1
hp-ux nên không có tham số nào
soField

@soField Vì vậy, bạn thấy đó, tốt hơn là (cho tất cả chúng ta) đăng dữ liệu này ở đầu câu hỏi của bạn ...
mosg

2
find cũng không có -empty trên solaris, nhưng nó có -depth để thực thi theo dõi chiều sâu đầu tiên để các thư mục con trống có thể bị xóa trước khi thư mục mẹ được kiểm tra xem có trống không.
eirikma

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

Đây là phiên bản mà tôi thấy thú vị nhất. Nếu được thực thi từ bên trong thư mục , nó sẽ xóa tất cả các thư mục trống bên dưới (một thư mục được coi là trống nếu nó chỉ chứa các thư mục trống).

Tùy chọn mindepth ngăn chính thư mục đó bị xóa nếu nó bị trống.


2
Bạn có thể làm theo điều này rmdir --ignore-fail-on-non-empty -p directoryđể thoát khỏi cha mẹ.
Pete Peterson

@Pete Peterson Lệnh của tôi dường như loại bỏ các thư mục chỉ chứa các thư mục trống khác (đó là điều mà OP dường như cũng muốn). Tôi lưu ý rằng lệnh của bạn thường sẽ để người dùng trong một thư mục bị thiếu i-node ngay cả khi họ hoàn thành những gì họ muốn, điều này có thể gây nhầm lẫn cho họ. Có lẽ tôi đang thiếu điểm.
Tiến sĩ Person Person II

23

find . -type d -empty

tìm và liệt kê các thư mục trống và thư mục con trong cây hiện tại. Ví dụ: danh sách kết quả gồm các dirs và subdirs trống:

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

Không có hoạt động nào được thực hiện trên các thư mục. Chúng được liệt kê đơn giản. Điều này làm việc cho tôi.


16

Chỉ cần tìm những tờ tiền trống

Để chỉ tìm các thư mục trống (như được chỉ định trong tiêu đề câu hỏi), câu trả lời của mosg là đúng:

find -type d -empty

Nhưng -emptycó thể không khả dụng trên findcác phiên bản rất cũ (đây là trường hợp của HP-UX chẳng hạn). Nếu đây là trường hợp của bạn, hãy xem các kỹ thuật được mô tả trong phần bên dưới Thư mục có trống không? .

Xóa dirs trống

Điều này hơi phức tạp: Giả sử một thư mục MyDirchứa các thư mục trống. Sau khi loại bỏ các thư mục trống này, MyDirsẽ trở thành một thư mục trống và cũng nên được gỡ bỏ. Do đó, tôi sử dụng lệnh rmdirvới tùy chọn --parents(hoặc -p) cũng xóa các thư mục mẹ khi có thể:

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

Trên findphiên bản cũ hơn , câu lệnh +chưa được hỗ trợ, do đó bạn có thể sử dụng ;thay thế:

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

Một thư mục trống?

Hầu hết các câu trả lời này giải thích cách kiểm tra xem thư mục có trống hay không. Vì vậy, tôi cung cấp ở đây ba kỹ thuật khác nhau mà tôi biết:

  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

    Một biến thể:

    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

    Giải trình:

    • find -prunetương tự như find -maxdepth 0việc sử dụng ít ký tự hơn
    • find -type d chỉ in thư mục
    • find -empty in các thư mục và tệp trống

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

    Thủ thuật này là 100% bashnhưng gọi (sinh ra) một trình bao phụ. Ý tưởng là của Bruno De Fraine và được cải thiện bởi nhận xét của teambob . Tôi khuyên cái này nếu bạn sử dụng và nếu script của bạn không cần phải di động.

    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

    Lưu ý: không có sự khác biệt giữa thư mục trống và thư mục không tồn tại (và ngay cả khi đường dẫn được cung cấp là một tệp).

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

    Thủ thuật này được lấy cảm hứng từ bài báo của nixCraft được đăng vào năm 2007. Andrew Taylor đã trả lời vào năm 2008 và gr8can8dian vào năm 2011.

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

    hoặc phiên bản bashism một dòng:

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

    Lưu ý: ls trả về $?=2khi thư mục không tồn tại. Nhưng không có sự khác biệt giữa một tệp và một thư mục trống.


rmdir -vpđã giúp tôi rất nhiều vì tôi không chỉ cần xóa tất cả các dirs trống trong thư mục gốc, mà còn kiểm tra các dirs trống và dirs mẹ sau khi xóa một tệp. Trong tình huống của tôi, các dirs trống vẫn tốt miễn là chúng không ở trong cây mà tôi hiện đang xóa tệp khỏi đó. Cảm ơn!
Ethan Hohensee

2

Hàm đệ quy này dường như sẽ thực hiện thủ thuật:

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

Với cấu trúc thư mục mẫu này:

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

Kết quả của việc chạy hàm đó sẽ là:

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

mà bỏ lỡ /dir4/dirD. Nếu bạn di chuyển cuộc gọi đệ quy findempty "$dir"sau fi, hàm sẽ bao gồm thư mục đó trong kết quả của nó.


2

Làm thế nào về rmdir *? Lệnh đó sẽ không thành công trên các thư mục không trống.


Đôi khi tôi đã làm một điều gì đó, để dọn dẹp chung. Cũng đã thực hiện những việc như rmdir */*/* */* * Mặc dù điều đó không xử lý 'tệp chấm' nhưng sau đó trong các tình huống thủ công (làm sạch tệp dữ liệu), bạn thường không mong đợi "tệp chấm". Tuy nhiên, các phương pháp đệ quy dành cho việc dọn dẹp chung tự động hơn, đặc biệt là trong các cấu trúc thư mục rất lớn.
anthony

Trong một trường hợp phức tạp hơn vì tôi cần xóa các thư mục trống trong đó các thư mục 'trống' bao gồm có thể chứa một tệp 'readme'. Bất kỳ thứ gì khác trong thư mục và nó không phải là 'trống rỗng'. Trong ví dụ đó, cấu trúc thư mục liên quan đến hàng chục nghìn thư mục con.
anthony

1

Lệnh sau trả về 1 nếu một thư mục trống (hoặc không tồn tại) và 0 nếu không (vì vậy có thể đảo ngược mã trả về !trong tập lệnh shell):

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

0

Tôi đã tạo một cấu trúc đơn giản như sau:

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

test/test3/filechứa một số văn bản rác.

Phát hành find test -emptytrả về " test/test2/test2.2" là thư mục trống duy nhất.


op yêu cầu kiểm tra / test2 cũng được trả lại

Thật. Nhưng tôi nghĩ anh ấy có thể đọc trang tìm người đàn ông để đi xa hơn. Một tập lệnh điều chỉnh độ sâu dựa trên kết quả sẽ hoạt động tốt.
James Sumners

Đây là phiên bản hữu ích nhất cho việc sử dụng mye, nhờ
Andreas

0

một cách tiếp cận đơn giản sẽ là,

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

cũng thế,

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}'
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.