Trích xuất các tệp .gz có trong một thư mục


13

Tôi có một thư mục chứa khoảng 320116 tệp .pdb.gz. Tôi muốn giải nén tất cả. Nếu tôi sử dụng gunzip * .gz, nó sẽ báo lỗi, danh sách đối số quá dài. Thư mục có dung lượng khoảng 2GB. Xin vui lòng cho tôi một gợi ý thích hợp.


Nếu bạn sẽ phải làm việc với cấu trúc thư mục này trong thời gian dài, hãy chia thư mục này thành nhiều phần. Ví dụ dựa trên thời gian sửa đổi tệp hoặc tên tệp.
dan

Có tôi phải làm việc lâu dài. chúng đã được trích xuất bây giờ tôi muốn chia nhỏ và phân loại chúng thành ba thư mục trên cơ sở tên của chúng. Có một kịch bản shell để làm như vậy?
Lily Sharpton

Tôi đề nghị bạn tìm kiếm các câu hỏi tương tự ở đó. Nếu bạn không tìm thấy một cái phù hợp với nhu cầu của mình, hãy hỏi câu hỏi mới của riêng bạn.
dan

Câu trả lời:


26
find . -name '*.pdb.gz' -exec gunzip {} +

-exec gunzip {} +sẽ cung cấp gunzipnhiều nhưng không quá nhiều tên tệp trên dòng lệnh của nó. Điều này hiệu quả hơn so với -exec gunzip {} \;việc bắt đầu một gunzipquy trình mới cho mỗi và mọi tệp.


3
Một find, ít hơn gunzip!
dan

2
Lưu ý rằng "+" là một GNUism và do đó sẽ không hoạt động trên các hệ thống không phải GNU như * BSD.
Phục hồi Monica - M. Schröder

3
Các phiên bản sau của BSD findcho phép ký hiệu "+". Xem, ví dụ, các findtrang người đàn ông cho BSD 10.1 . Cũng áp dụng cho OS X (ít nhất 10.9 trở lên, có thể sớm hơn).
huyết tương

7

Bất cứ khi nào bạn gặp lỗi "danh sách đối số quá dài", bạn có thể xử lý xung quanh nó bằng cách gọi lệnh mong muốn nhiều lần, mỗi lần với một tập hợp con các đối số bạn muốn sử dụng. xargslà một công cụ giúp bạn làm điều đó tự động.

find . -type f -a -name \*.pdb.gz -print0 | xargs -0 gunzip

điều này không có hiệu quả tương tự như -execdir gunzip "{}" \;tức là xargs sẽ gọi gunzip riêng cho từng tệp? Đó là cách đọc trang của tôi.
gogoud 19/03/2015

5
Không, xargssẽ nhồi càng nhiều tên tệp sẽ phù hợp với gunzipdòng lệnh. Thử nó! echo a b c d e f | xargs echochỉ gọi echomột lần với tất cả 6 đối số để bạn thấy một dòng đầu ra (lệnh khá vô dụng để thực thi mặc dù !!!!) trong khi nếu bạn buộc xargschỉ cung cấp tối đa 3 đối số cho mỗi lần gọi lệnh echo a b c d e f | xargs -n 3 echothì bạn sẽ nhận được 2 dòng đầu ra .
Celada

4
Một ưu điểm khác của việc sử dụng xargslà, với -Ptùy chọn, bạn có thể chạy gunzipsong song nhiều quy trình, điều này (tùy thuộc vào các tham số chính xác của hệ thống của bạn) có thể diễn ra nhanh hơn.
psmears 19/03/2015

cảm ơn con trỏ tới -P, @psmears. Bây giờ tôi cũng đã học được điều gì đó!
Celada

1

Tôi nghĩ điều này sẽ hoạt động, nó chuyển đường dẫn / tên của từng tệp riêng lẻ sang gunzip để xử lý:

find /my/dir -name "*.pdb.gz" -execdir gunzip "{}" \;

1
Điều đó sẽ thực thi gunzip một lần cho mỗi tệp. Xem câu trả lời của John1024 cho một cách hơi khác để tránh sự không hiệu quả.
Celada

@Celada Đây là cố ý; mối quan tâm của tôi là việc sử dụng + một lần nữa có thể dẫn đến một thông báo lỗi vì quá tải gunzip. Nếu phương pháp của John1024 hoạt động, nó hiệu quả hơn về mặt kỹ thuật, nhưng phương pháp của tôi sẽ hoạt động nếu không.
gogoud 19/03/2015

1
findvới +xargsđược thiết kế rõ ràng với chính xác vấn đề đó trong tâm trí. Họ sẽ luôn cung cấp càng nhiều đối số càng tốt, trong khi không vượt quá giới hạn của hệ điều hành. Bởi vì, nhân tiện, nó một giới hạn hệ điều hành, không có gì để làm với gunzip.
Celada

1
@Celada ok cảm ơn vì thông tin đó, vì vậy có lẽ với gunzip '+' có thể được gọi nhiều lần, nhưng ít hơn 320.000 lần?
gogoud 19/03/2015

1
chính xác.
Celada


1

Nếu bạn có một máy đa lõi, có lẽ bạn sẽ thấy rằng việc sử dụng gunzipsẽ không phát huy tối đa khả năng của máy. Cho rằng bạn sẽ cần phải chạy nhiều gunzips song song. Để theo dõi những gì được thực hiện trong đó thiết bị đầu cuối bằng tay là cồng kềnh, nhưng bạn có thể dễ dàng làm điều đó với GNU song song:

find . -name "*.gz" | parallel -X gunzip {}

1
Sẽ không thất bại vì danh sách đối số parallelquá dài?
dùng253751

@immibis Vâng, tôi đã quên vấn đề ban đầu, tôi sẽ cập nhật bài đăng của mình
Anthon

Sẽ không phải là vẫn thất bại bởi vì danh sách đối số để findquá dài?
dùng253751

1
có nhưng bạn đang vượt qua tất cả tên tệp trên finddòng lệnh của.
dùng253751

Có vẻ như đây không phải là một ngày tốt để trả lời các câu hỏi, tôi đã quên trích dẫn cuộc tranh luận với-name
Anthon

-1

Nó là không cần thiết để sử dụng findcho việc này, vì bạn đã không đề cập đến các thư mục con. Những gì bạn cần làm là:

for f in *.gz;do gunzip $f;done

4
Bạn làm cần findnếu bạn không muốn để đẻ trứng 320.116 gunzipquá trình, giống như vòng lặp này không.
John WH Smith
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.