Làm cách nào để sao chép tất cả các tệp trong một thư mục không bao gồm các tệp đang được ghi?


12

Tôi tải nhiều tệp vào một thư mục downloadingthông qua HTTPie . Một tập lệnh bash nhằm xử lý các tệp đã tải xuống và tôi đã cố gắng sao chép các tệp đã tải xuống vào một thư mục khác như

find /folder/downloading -type f -exec mv '{}' /folder/downloaded \;

nhưng điều này cũng sao chép các tập tin chưa được hoàn thành. Tôi đã cố gắng hạn chế chuyển sang các tập tin cũ hơn bằng cách thêm -mmin +5vào lệnh. Lệnh hiệu quả để rời khỏi các tệp đang được ghi và chỉ chuyển các tệp đã tải xuống là gì?


Nếu sao chép vào cùng một hệ thống tệp và bạn đặt trình tải xuống thành không đổi tên (tải xuống để %.partsau đó đổi tên thành%). Sau đó, nếu trình tải xuống hoạt động tốt (không có gì khác lạ), thì bạn sẽ có thể đổi tên mvcác tệp ( ).
ctrl-alt-delor

1
Những loại xử lý bạn đang cố gắng làm? Có nhiều khả năng là một tùy chọn đơn giản hơn nhiều, như sử dụng một đường ống dẫn.
vườn

Câu trả lời:


11

Không hiệu quả lắm, nhưng bạn có thể làm:

find /folder/downloading -type f -exec sh -c '
  for file do
    lsof -F a "$file" | grep -q w || mv "$file" /folder/downloaded
  done' sh {} +

Đó là kiểm tra xem các tập tin không được liệt kê với một wnghi thức achế độ ccess trong li st của obút fIles trước mo ving.

Việc psmisctriển khai fusernhư thường thấy trên các hệ điều hành dựa trên Linux có một -wchức năng (để kiểm tra các tệp đang mở để ghi) nhưng thật không may, nó chỉ hoạt động -kđể tiêu diệt các tiến trình tương ứng. Tuy nhiên, có vẻ như bạn vẫn có thể sử dụng nó bằng cách sử dụng tín hiệu giả 0 mà không làm gì:

find /folder/downloading -type f -exec sh -c '
  for file do
    fuser -s -w -k -0 "$file"  || mv "$file" /folder/downloaded
  done' sh {} +

Xóa -s(hoặc thậm chí thay thế nó bằng -v) nếu bạn muốn xem quá trình (đang) ngăn chặn việc di chuyển.

Lưu ý rằng nếu bạn không chạy các lệnh đó với tư cách là siêu người dùng, bạn sẽ chỉ nhận được thông tin về các quy trình của mình. Nếu các quá trình tải xuống các tệp đang chạy như một người dùng khác, chúng sẽ vẫn không bị phát hiện.

Cũng lưu ý rằng trừ khi bạn di chuyển các tệp sang một hệ thống tệp khác, việc di chuyển các tệp sẽ không ngăn bất kỳ quy trình nào hiện đang ghi vào tệp để hoàn tất ghi vào tệp.

Tuy nhiên, phụ thuộc vào những gì họ đã được thiết kế để làm sau đó, họ có thể bị nhầm lẫn nếu sau khi họ hoàn thành văn bản, tập tin không còn ở đó (ví dụ nếu họ muốn thay đổi một số thuộc tính của tập tin sau khi tải về nó và làm như vậy không thông qua bộ mô tả tệp (như chmod()vs fchmod(), hoặc utimes()không thể được thực hiện thông qua bộ mô tả tệp)).


Câu hỏi Shell: Tôi nghĩ rằng tôi hiểu mã của bạn với một ngoại lệ. Cái -execđang chạy shvới một lệnh ( -c '...') và {} +bảo nó đặt nhiều kết quả vào lệnh đó cùng một lúc. Điều tôi không hiểu là tại sao lại có shlệnh khác sau lệnh. Tôi đang thiếu gì?
Joe

2
@Joe, đó là những gì đi vào tập lệnh nội tuyến $0. Đó là, nó đặt tên cho tập lệnh nội tuyến đó. Tên đó có thể được sử dụng trong các thông báo lỗi như <name>: fuser: command not foundví dụ, vì vậy, shnói chung là một lựa chọn tốt trong trường hợp này để làm rõ thông báo lỗi đó là gì (đó cũng sẽ là gì nếu chúng ta không đưa ra bất kỳ đối số nào sau kịch bản nội tuyến).
Stéphane Chazelas
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.