Giải nén nhiều tập tin cùng một lúc


27

Tôi có hơn 200 .ziptệp trong một thư mục. Tôi không muốn giải nén từng cái một. Tôi muốn trích xuất những người sử dụng lệnh đơn hoặc tập lệnh. Làm thế nào để làm điều đó.

Câu trả lời:


38

Nếu bạn thực sự muốn giải nén chúng song song, bạn có thể làm

for i in *zip; do unzip "$i" & done

Tuy nhiên, điều đó sẽ khởi chạy N process cho các tệp N .zip và có thể rất nặng trên hệ thống của bạn. Để có cách tiếp cận được kiểm soát nhiều hơn, chỉ khởi chạy 10 quy trình song song cùng một lúc, hãy thử điều này:

find . -name '*.zip' -print0 | xargs -0 -I {} -P 10 unzip {}

Để kiểm soát số lượng quy trình song song được khởi chạy, hãy thay đổi -Pthành bất cứ điều gì bạn muốn. Nếu bạn không muốn tái diễn vào các thư mục con, thay vào đó, hãy làm điều này:

find . -maxdepth 1 -name '*.zip' -print0 | xargs -0 -I {} -P 10 unzip {}

Ngoài ra, bạn có thể cài đặt song song GNU theo đề xuất của @OleTange trong các nhận xét và chạy

parallel unzip ::: *zip

3
Chạy song song là một ý tưởng hay, nhưng liệu I / O của đĩa không phải là nút cổ chai lớn?
Paddy Landau

1
@PaddyLandau không chắc chắn, tôi phải kiểm tra. Nó sẽ phụ thuộc vào tốc độ của thuật toán giải nén so với tốc độ của đĩa tôi tưởng tượng.
terdon

Sử dụng -exechoặc -execdirthay vì đường ống đến xargs. Không chỉ đơn giản để hiểu, mà còn ít bị lỗi hơn và sử dụng ít tài nguyên hệ thống hơn. find . -name '*.zip' -exec unzip {} ';'(Bạn phải trích dẫn dấu chấm phẩy.)
Paddy Landau

@PaddyLandau lý do duy nhất tôi chuyển sang xargs là chạy mọi thứ song song như OP yêu cầu. -exec \;(bạn có thể thoát dấu chấm phẩy, không cần dấu ngoặc kép), sẽ chạy từng lệnh một cách tuần tự. -exec +tốt hơn nhưng nó sẽ không hoạt động ở đây vì đó không phải là cách unziphoạt động.
terdon

Tôi nghĩ rằng chúng tôi đã hiểu OP khác nhau. Bạn đọc anh ta như muốn nó song song, trong khi tôi hiểu anh ta có nghĩa là một lệnh duy nhất thay vì nhiều lệnh. Chà, anh ấy có cả hai phương pháp bây giờ :)
Paddy Landau

17

Lệnh song song GNU rất phù hợp với loại điều này. Sau:

$ sudo apt-get install parallel

Sau đó

ls *.zip | parallel unzip

Điều này sẽ sử dụng nhiều lõi như bạn có, giữ cho mỗi lõi bận rộn với một giải nén, cho đến khi tất cả chúng được thực hiện.


echo *.zipThay vào đó, nên sử dụng một ý tưởng tốt hơn để ngăn bí danh ls có thể lén lút trong thông tin bổ sung. Tuy nhiên, điều này có cùng một vấn đề như câu trả lời của @ Guru, nó phá vỡ tên tệp chứa khoảng trắng.
nyuszika7h

1
@ nyuszika7h Ngược lại với xargsGNU Parallel không phá vỡ tên tệp chứa dấu cách / tab / quote. Chỉ khi tên tệp chứa dòng mới, bạn sẽ phải chăm sóc thêm. Ví dụ: bằng cách sử dụng:parallel unzip ::: *.zip
Ole Tange

@ nyuszika7h - Đây là những lý do tốt để tránh cả các lệnh tiêu chuẩn răng cưa đặt khoảng trắng trong tên tệp.
Wayne Conrad

@ nyuszika7h sử dụng echocũng tệ như sử dụng ls. Globbing và một vòng lặp while là an toàn nhất.
terdon

1
@NateEldredge Mặc dù cơ hội đó đã trở lại lớn hơn vào thời điểm khi các hệ thống chỉ có một đĩa từ tính, ngày nay với RAID có nhiều trục quay và đĩa flash thì cơ hội đó nhỏ hơn. Điều tốt nhất để làm là tất nhiên để đo lường và xem hệ thống của bạn hoạt động như thế nào . Gần đây tôi đã sử dụng một RAID 40 trục chính trong đó độ song song tối ưu cho các quá trình đói I / O là 10: Nó không tăng tốc độ gấp 10 lần - chỉ 6x, nhưng ít hơn 10 quy trình cho ít hơn 6 lần.
Ole Tange

12

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

Đầu tiên thay đổi thư mục trong thiết bị đầu cuối sang thư mục có chứa các tệp .zip:

cd /path

Sau đó thực hiện lệnh này để giải nén tất cả các tệp .zip:

for z in *.zip; do unzip "$z"; done

10

Nếu bạn có nhiều .ziptệp trong thư mục của mình và bạn muốn giải nén tất cả chúng thì hãy mở terminal và vào thư mục của bạn bằng cách sử dụng:

cd <path_to_folder>

Bây giờ sử dụng lệnh này để giải nén tất cả các .ziptệp của bạn :

ls *.zip | xargs -n1 unzip

3
Điều này sẽ thất bại nếu bất kỳ tên tệp nào chứa khoảng trắng.
terdon

1
Ừ bạn đúng rồi đó.
g_p

echo *.zipThay vào đó, nên sử dụng một ý tưởng tốt hơn để ngăn lsbí danh có thể lén lút trong thông tin bổ sung, tuy nhiên điều đó vẫn không khắc phục được vấn đề khoảng trắng.
nyuszika7h

1
@OleTange Trong trường hợp bạn không nhận thấy, tôi đã nói rằng nó vẫn không thành công với tên tệp có khoảng trắng trong đó.
nyuszika7h

1
Không bao giờ phụ thuộc vào đầu ra từ lscho các tập lệnh, vì đầu ra của nó không được xác định rõ giữa các phiên bản. Thay vào đó hãy nhìn vào câu trả lời từ @terdon vì nó giải quyết được tất cả các vấn đề của giải pháp này.
Paddy Landau

6

Bạn có thể sử dụng find với -execnhư vậy,

find . -name "*.zip" -exec unzip {} \;

Điều này sẽ hoạt động nếu tập tin có một khoảng trắng trong tên.


3

Một phương pháp không đầu cuối.

Chỉ cần chọn các tệp zip, nhấp chuột phải vào một và chọn extract here. Bạn có thể chọn tất cả hoặc chỉ một số tệp zip tại một thời điểm.


1

unzip \*.zip hoặc là unzip '*.zip'

Rõ ràng là unzip *.zipkhông hoạt động, vì shell mở rộng nó unzip foo.zip bar.zip ...unzipgiải thích tên tệp đầu tiên là tệp zip và tên tệp sau dưới dạng tệp để trích xuất từ ​​tệp zip đó.

Tuy nhiên, unzipcó một chút khác thường giữa các lệnh Unix ở chỗ nó thực hiện mở rộng toàn cầu. Nếu *shell không được mở rộng, giải nén sẽ thực hiện điều đó và đặt lại tất cả các tên tệp kết quả dưới dạng tệp zip cần xử lý. Vì vậy, trong trường hợp đặc biệt này, người ta có thể thoát khỏi mà không cần một forvòng lặp hoặc xargstương tự.

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.