Làm thế nào để xóa unextract Tập tin zip?


52

Tôi trích xuất một tệp zip vào một thư mục không trống. Tệp zip có rất nhiều tệp và phân cấp sâu, được hợp nhất với cây hiện có của thư mục đích. Làm cách nào tôi có thể xóa các tệp và thư mục được tạo bằng cách giải nén mà không hủy các tệp và thư mục đã có ở đó? Tất nhiên, tôi vẫn có tệp zip mà tôi đã hợp nhất, vì vậy thông tin là có.


Umm cảm ơn vì đã chấp nhận, nhưng đó thực sự là ý tưởng của @ jjin. Tôi không nhận thức được các lqtùy chọn cho unzizp, tôi chỉ thêm một số thủ thuật * nix cổ điển xung quanh câu trả lời chính của anh ấy.
terdon

Không sao đâu, tôi không quan tâm lắm đâu. Tôi đã thêm phiên bản xử lý khoảng trắng khác nhau của riêng mình.
jjlin

@terdon Vâng ... Tôi cũng nêu lên câu trả lời của jjlin, nhưng tôi chỉ có thể chấp nhận một câu trả lời.
mafp

Để tham khảo trong tương lai, luôn luôn thực hiện một trong các thao tác sau với kho lưu trữ không quen thuộc ở bất kỳ định dạng nào: 1) Trích xuất nó vào một thư mục trống hoặc 2) Liệt kê trước (giải nén -l) trước khi giải nén để bạn có thể thấy nó có khó chịu như thế này không. Lưu trữ được thực hiện mà không có một thư mục cấp cao nhất với tất cả mọi thứ dưới đó là hình thức xấu. Khi thực hiện với tar, chúng thực sự được gọi là bom tar, vì vậy tôi đoán đây có thể được gọi là bom zip.
Joe

@Joe Nó có công dụng của nó. Các gói LaTeX, ví dụ, có thể có foo.tds.zipdạng. Các khóa này hợp nhất thành một cây TEXMF, rất thuận tiện. Nhưng nếu bạn muốn loại bỏ một gói như vậy, bạn sẽ phải đối mặt với vấn đề tôi đã mô tả.
mafp

Câu trả lời:


28

Câu trả lời của jjlin là con đường để đi. Tôi chỉ muốn thêm một vài lựa chọn cho các thư mục:

  • Xóa tất cả các tệp được giải nén, không có thư mục :

    unzip -lqq file.zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm "$n"; done
  • Xóa các tệp được giải nén và các thư mục trống

    unzip -lqq file.zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm "$n"; done; rmdir *

    Không có tùy chọn, rmdirchỉ xóa các thư mục trống, nó sẽ để lại các tệp và các thư mục không trống để bạn có thể chạy nó một cách an toàn *.

  • Xóa mọi thứ được trích xuất, nhưng nhắc nhở xác nhận trước mỗi lần xóa:

    unzip -lqq file.zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm -ri "$n"; done; rmdir *

    Các -ilá cờ sẽ gây ra rmđể nhắc nhở trước mỗi di chuyển, bạn có thể chọn Yes hoặc No.

  • Xóa mọi thứ được trích xuất, bao gồm các thư mục:

    unzip -lqq file.zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm -rf "$n"; done

Xóa các thư mục trống được thực hiện dễ dàng với find: find * -depth -type d -exec rmdir {} +và bỏ qua tất cả các Directory not emptytin nhắn. Có thể là hợp pháp để rút ngắn điều này find * -type d -deletekhi -deletetùy chọn bật -depthnhưng tôi chưa xác minh rằng -deletesẽ không xóa một thư mục không trống.
Adrian Pronk

@AdrianPronk thì không:find: cannot delete './foo': Directory not empty
terdon

28

Bạn có thể sử dụng unzip -lqq <filename.zip>để liệt kê nội dung của tệp zip; điều này sẽ bao gồm một số thông tin không liên quan mà bạn sẽ cần phải lọc ra. Đây là một lệnh làm việc cho tôi:

unzip -lqq file.zip | awk '{print $4;}' | xargs rm -rf

Các awklệnh trích xuất chỉ là tên của các tập tin và thư mục. Sau đó, kết quả được thông qua xargsđể xóa tất cả mọi thứ. Tôi đề nghị thực hiện một lệnh chạy khô (nghĩa là bằng cách bỏ qua xargs rm -rfphần đó) trước để đảm bảo kết quả là chính xác.

Lệnh trên sẽ có vấn đề xử lý các đường dẫn có khoảng trắng. Phiên bản (phức tạp hơn) này sẽ khắc phục điều đó:

unzip -lqq file.zip | awk '{$1=$2=$3=""; sub(/ */, "", $0); printf "%s%s", $0, "\0"}' | xargs -0 rm -rf

Điều này đã khá gần với những gì tôi đã nghĩ, nhưng unzip -lqqcũng liệt kê các thư mục chứa trong zip. Bây giờ, tôi sẽ để tất cả các thư mục một mình. Làm thế nào để xóa tất cả các thư mục trống trong cây có thể là một câu hỏi tiếp theo.
mafp

@mafp Đó là một điểm tốt về các thư mục. Bạn có thể thêm grep -v '/$'vào đường ống để bỏ qua việc xóa các thư mục (tất cả đều có dấu gạch chéo, AFAICT).
jjlin

@terdon Thật ra tôi nghĩ vấn đề bắt đầu từ lúc awk, vì chỉ in $ 4 sẽ không in được đường dẫn đầy đủ.
jjlin

Tôi không nghĩ bạn nên sử dụng -rtùy chọn rm: điều đó dường như đang gây rắc rối, đặc biệt là khi kết hợp với -ftùy chọn. Tôi sẽ không sử dụng -ftùy chọn nào trong kịch bản này.
Adrian Pronk

1
@jjlin: grep -v '/$'sẽ chỉ bỏ qua các mục trong thư mục trong tệp ZIP. Chúng vẫn sẽ bao gồm các mục là các tệp đơn giản trong tệp ZIP nhưng là các thư mục tồn tại trong thư mục đích. Vì lý do này, sẽ là khôn ngoan nếu bỏ qua-r
Adrian Pronk

11

Với chuyển đổi -Z1, giải nén sẽ liệt kê chính xác một tệp trên mỗi dòng (và không có gì khác).

Bằng cách này, bạn có thể sử dụng

unzip -Z1 | xargs -I {} rm '{}'

để xóa tất cả các tệp được trích xuất từ ​​tệp zip.

Lệnh

unzip -Z1 | xargs -I {} rm -rf '{}'

cũng sẽ xóa các thư mục, nhưng bạn phải cẩn thận. Nếu các thư mục đã tồn tại trước khi giải nén tệp zip, tất cả các tệp tồn tại trong các thư mục đó cũng sẽ bị xóa.


Nếu bạn định giải nén lại tệp zip, thì có một cách tiếp cận khác được đảm bảo để xử lý các tên tệp lạ.

Đầu tiên giải nén tệp zip nơi bạn dự định giải nén nó:

unzip file.zip -d elsewhere

Bây giờ, thay đổi vào thư mục mà bạn trích xuất các tệp do nhầm lẫn và thực hiện lệnh sau:

find elsewhere -type f -printf "%P\0" | xargs -0 -I {} rm '{}'
  • -type f chỉ tìm thấy tập tin (không có thư mục).

  • %P\0là đường dẫn tương đối (không có elsewhere/), theo sau là ký tự null.

  • -0làm cho xargs các dòng riêng biệt bằng các ký tự null. Điều này đáng tin cậy hơn, vì - về lý thuyết - tên tệp có thể chứa các ký tự dòng mới.


Để xử lý các thư mục còn sót lại, bạn có thể thực thi lệnh:

find -type d -exec rmdir -p {} \; 2> /dev/null
  • -type d chỉ tìm thấy thư mục.

  • -exec rmdir -p {} \;thực thi rmdir -p {}cho mọi thư mục đã được tìm thấy.

    {}là thư mục đã được tìm thấy và -pchuyển đổi làm cho rmdir loại bỏ các thư mục mẹ trống của nó.

  • 2> /dev/null ngăn chặn các thông báo lỗi sẽ phát sinh từ việc cố gắng xóa các thư mục không trống hoặc đã xóa trước đó.


Trang người đàn ông liên quan:


+1 để khiến tôi đọc zipinfotrang người đàn ông.
terdon

Vâng, gee, điều đó làm cho nó dễ dàng hơn một chút. :)
jjlin

2

Đây là một giải pháp thậm chí dễ dàng và an toàn hơn (tôi nghĩ)

zip -m getmeoutofhere.zip `unzip -lqq myoriginalzipfile.zip`
rm getmeoutofhere.zip

Điều này đang làm: Lệnh unzip được trích dẫn sẽ tạo ra một danh sách những gì có trong tệp gốc của bạn.

zip -m sau đó sẽ sử dụng danh sách đó để thêm add đó vào getmeoutofhere.zip và xóa nó khỏi thư mục gốc (vì vậy về mặt lý thuyết, nó nên không liên quan đến myorigenfile.zip.

Nhược điểm là giải nén -lqq sẽ tạo ra một số văn bản bổ sung, ngày, giờ, kích thước tệp, v.v. Tên).

Xin lưu ý rằng điều này sẽ không xóa bất kỳ thư mục đã được tạo trong quá trình giải nén ban đầu.


Cách tiếp cận thú vị, sẽ khám phá thêm.
mafp

1

Nếu bạn trích xuất các tệp sao cho dấu thời gian sửa đổi trong kho lưu trữ không được lưu giữ trong các bản sao được trích xuất (nhưng các tệp được trích xuất có thời gian sửa đổi thông thường) thì cách đúng để tấn công điều này là thông qua thời gian sửa đổi. Tất cả các tệp được trích xuất có dấu thời gian sửa đổi mới hơn so với tệp hiện có được sửa đổi gần đây nhất trong thư mục đó.

Đây là một tình huống đơn giản.

Giả sử rằng không có tệp nào trong thư mục hiện tại bị chạm trong ít nhất 24 giờ. Do đó, bất cứ điều gì đã được sửa đổi trong 24 giờ qua là rác từ zipfile.

$ find . -mtime -1 -print0 | xargs -0 rm

Điều này cũng sẽ tìm thấy một số thư mục, nhưng rmsẽ để chúng một mình. Họ có thể bị xử lý trong một lần thứ hai:

$ find . -mtime 1 -type d -print 0 | xargs -0 rmdir

Bất kỳ thư mục nào được sửa đổi gần đây đều được sửa đổi bởi zip. Nếu rmdirloại bỏ thành công chúng, điều đó có nghĩa là chúng trống. Các thư mục trống được chạm bởi zip có thể được tạo bởi nó: tức là đến từ kho lưu trữ. Chúng tôi không thể chắc chắn 100%. Có thể công việc giải nén đã đưa một số tệp vào một thư mục hiện có trống.

Nếu findđộ chi tiết trong 24 giờ không đủ tốt cho công việc, bởi vì các tệp trong cây đã được sửa đổi gần đây, thì tiếp theo tôi sẽ xem xét một điều đơn giản: giả sử rằng công việc giải nén không đưa bất cứ điều gì vào các thư mục con hiện có. Điều đó có nghĩa là, mọi thứ được giải nén đều là một tệp ở cấp cao nhất hoặc thư mục con mới chưa có ở đó, do đó không chứa gì ngoài tài liệu từ zip. Sau đó:

# list directory in descending order of modification time
$ ls -1t > filelist  # descending order of modification time

Bây giờ chúng tôi mở filelisttrong một trình soạn thảo văn bản và xác định mục nhập đầu tiên trong danh sách không xuất phát từ zip. Chúng tôi xóa mục đó và mọi thứ khác sau nó. Những gì còn lại là các tập tin và thư mục đến từ zip. Đầu tiên chúng tôi kiểm tra trực quan các vấn đề như khoảng trắng trong tên và sự xuất hiện của dấu ngoặc kép cần được thoát. Sau đó, chúng tôi có thể thêm dấu ngoặc kép xung quanh mọi thứ, nếu cần: Giả sử sau đây bạn sử dụng Vim:

:%s/.*/"&"/

Sau đó tham gia tất cả thành một dòng lớn:

:%j

Bây giờ chèn rm -rfvào phía trước của nó:

Irm - rf<ESC>

Chạy dòng dưới con trỏ dưới dạng lệnh shell:

!!sh<Enter>

Chắc chắn, tôi sẽ không tự động hóa các bước của nhiệm vụ này, do rủi ro xóa các tệp đã có sẵn hoặc làm hỏng do vấn đề tên tệp.

Nếu bạn đang đi theo con đường rõ ràng để có được danh sách các đường dẫn trong zip, sau đó chụp nó vào một tệp, xem xét nó rất cẩn thận và chuyển nó thành một loại bỏ sau khi thực hiện bất kỳ chỉnh sửa cần thiết nào.

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.