2010-04-25 14 views
6

Tôi đã xem các vòng để giải nén tất cả các tệp zip trong một thư mục. Tuy nhiên, trước khi tôi chạy này, tôi thà chắc chắn rằng những gì tôi sắp chạy sẽ làm việc ngay:Vòng lặp shell có thể giải nén tất cả các tệp trong một thư mục không?

for i in dir; do cd $i; unzip '*.zip'; rm -rf *.zip; cd ..; done 

Về cơ bản tôi muốn nó nhìn vào sản lượng của "dir" nhìn thấy tất cả các thư mục, đối với mỗi cd thư mục vào nó, giải nén tất cả các kho lưu trữ zip, sau đó loại bỏ chúng, sau đó cd trở lại và làm điều đó một lần nữa cho đến khi không có nhiều hơn nữa.

Đây có phải là điều tôi nên làm trong một lệnh duy nhất hay tôi nên cân nhắc thực hiện việc này trong Perl?

+1

Xin chào và chào mừng bạn đến với StackOverflow. Để làm cho mã của bạn dễ đọc hơn, vui lòng sử dụng mã thẻ –

+1

để biết thông tin của bạn, bạn có thể sử dụng cd - để quay lại thư mục trước đó. – Aif

+0

@Patrick done :) – DVK

Trả lời

1

phần kiểm tra:

find . -type d -exec sh -c "cd \"{}\" ; unzip \"*.zip\" ; rm \"*.zip\" " \; 

thực hiện chuỗi cd/unzip/rm cho mỗi subdir.

+0

Cho đến nay công trình này, nơi mà câu trả lời khác không thể thực hiện các công cụ như "Tên thư mục có không gian", tuy nhiên, nó không xóa các tệp nén .zip. – helpwithshell

+0

Tôi nghĩ bạn phải sử dụng 'tìm ... | xargs -0 ... 'để xử lý khoảng trắng, hoặc làm dấu ngoặc kép thoát khỏi công việc? – Anycorn

+0

Cuối cùng tôi đã có thể sửa đổi dòng lệnh của bạn thành: tìm. -tên "* .zip" -exec sh -c "rm -rf \" {} \ "" \; để xóa tất cả các lưu trữ .zip còn lại. cảm ơn – helpwithshell

1

Sử dụng * để có được nội dung của thư mục hiện hành:

for i in *; do cd "$i"; ...etc... ; done 

Bạn cũng nên chắc chắn rằng một cái gì đó là một thư mục trước khi cố gắng cd vào nó. Trong bash, việc này được thực hiện như sau:

if [ -d "$i" ]; then ...etc... ; fi 

Bạn cũng nên cẩn thận kiểm tra xem thao tác giải nén đã thành công trước khi xóa tệp zip. Không cần sử dụng xóa đệ quy để xóa một tệp.

Tôi nghĩ rằng điều này đang đẩy giới hạn cho những gì nó hợp lý để làm một dòng duy nhất. Đặt nó vào một kịch bản shell và định dạng nó trên nhiều dòng.

2

Bạn sẽ ổn thôi. Để gỡ lỗi, chỉ cần tiền tố tất cả các lệnh trong vòng lặp với echo sẽ cho bạn biết cách các biến mở rộng. Bạn cũng có thể luôn sử dụng rm -i để được yêu cầu thay vì làm rm tiếp tục với bất kỳ thứ gì có -f.

Dấu nháy đơn trong cuộc gọi unzip của bạn sẽ chỉ giải nén các tệp có tên *.zip, tức là * sẽ không mở rộng. Sử dụng dấu ngoặc kép thay vì (hoặc không có dấu ngoặc kép nào cả).

Vòng lặp của bạn bây giờ giả định rằng tất cả các thư mục $i đều nằm ngay dưới thư mục hiện tại. Một giải pháp tổng quát hơn là sử dụng ngăn xếp thư mục (pushdpopd);

for i in $dir; do 
    pushd $i 
    unzip *.zip 
    rm -rf *.zip 
    popd 
done 
+0

tôi đã phải thay đổi đầu tiên từ cho tôi trong thư mục để cho tôi trong *, nó giải nén công cụ, tuy nhiên đã có vấn đề với các tập tin có chứa không gian trong tên. – helpwithshell

+0

@help: Tôi ngầm giả định rằng 'dir' là một biến khi không phải ví dụ của tôi sai. Cố định ở đây và bây giờ giả định rằng 'dir' là một biến giữ danh sách thư mục. –

2

Một vài điểm thêm vào những gì người khác đã nói:

  • Nếu bạn đặt một tham số trong dấu ngoặc kép duy nhất, như trong '*.zip', vỏ sẽ không làm mở rộng thẻ hoang dã và giải nén sẽ cố gắng xử lý một kho lưu trữ được gọi theo nghĩa đen là *.zip
  • Không sử dụng -r làm thông số cho rm nếu bạn chỉ muốn xóa các tệp đơn lẻ. Đó là điều không cần thiết nguy hiểm vì bất kỳ việc đệ quy xóa các thư mục con nào cũng có thể không được dự định.
  • Bạn nên kiểm tra mã trở lại của unzip và chỉ loại bỏ các tập tin zip nếu giải nén đã thành công (ví dụ bạn có thể nói if unzip *.zip; then rm *.zip; fi, hoặc thậm chí sử dụng một for vòng rõ ràng để xử lý các tập tin zip từng người một)
0

Khi bạn muốn biết nếu một cái gì đó sẽ làm việc nhưng rất thận trọng của nó là hậu quả phá hoại, làm một chút tại một thời điểm:

Hãy chắc chắn rằng bạn sẽ có được các tập tin ngay:

for i in dir; do cd $i; echo $i; cd ..; done 

Đảm bảo bạn có thể giải nén tệp trước khi xóa các tệp:

for i in dir; do cd $i; unzip '*.zip'; cd ..; done 

Và trước khi bạn thực hiện toàn bộ, hãy sao lưu thư mục của bạn.