Bagaimana cara menyalin semua file dalam folder tidak termasuk file yang sedang ditulis?

12

Saya mengunduh banyak file ke folder downloadingmelalui HTTPie . Skrip bash bertujuan untuk memproses file yang diunduh, dan saya mencoba menyalin file yang diunduh ke folder lain sebagai

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

tetapi ini juga menyalin file, yang belum selesai. Saya mencoba membatasi transfer ke file yang lebih lama dengan menambahkan -mmin +5perintah. Apa perintah efisien untuk membiarkan file sedang ditulis dan hanya mentransfer file yang diunduh?

Googlebot
sumber
Jika menyalin ke sistem file yang sama, dan Anda mengatur pengunduh untuk tidak mengganti nama (unduh untuk %.partkemudian ganti nama menjadi%). Kemudian jika pengunduh berperilaku baik (tidak ada yang aneh), maka Anda harus dapat mengganti nama ( mv) file.
ctrl-alt-delor
1
Jenis pengolahan apa yang Anda coba lakukan? Kemungkinan besar ada opsi yang jauh lebih sederhana yang tersedia, seperti menggunakan pipa.
Gardenhead

Jawaban:

11

Tidak terlalu efisien, tetapi Anda bisa melakukannya:

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

Itulah cek bahwa file tersebut tidak terdaftar dengan writus amodus ccess dalam li st dari opena files sebelum mo ving.

The psmiscpelaksanaan fusersebagai biasanya ditemukan pada sistem operasi berbasis Linux memiliki -wfungsi (untuk memeriksa file terbuka untuk menulis) tetapi sayangnya hanya bekerja dengan -kmembunuh proses yang sesuai. Namun, tampaknya Anda masih dapat menggunakannya dengan menggunakan sinyal semu 0 yang tidak melakukan apa-apa:

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

Hapus -s(atau bahkan ganti dengan -v) jika Anda ingin melihat proses apa yang mencegah langkah tersebut.

Perhatikan bahwa jika Anda tidak menjalankan perintah itu sebagai pengguna super, Anda hanya akan mendapatkan informasi tentang proses Anda. Jika proses pengunduhan file berjalan sebagai pengguna yang berbeda, mereka akan tetap tidak terdeteksi.

Perhatikan juga bahwa kecuali Anda memindahkan file ke sistem file yang berbeda, memindahkan file tidak akan mencegah proses apa pun yang saat ini menulis ke file tersebut dari penyelesaian penulisan ke dalamnya.

Namun, tergantung dari apa yang telah mereka rancang untuk dilakukan setelahnya, mereka mungkin bingung jika setelah mereka selesai menulis, file tidak lagi ada (misalnya jika mereka ingin mengubah beberapa atribut file setelah mengunduhnya dan melakukannya tidak melalui deskriptor file (seperti chmod()vs fchmod(), atau utimes()yang tidak dapat dilakukan melalui deskriptor file)).

Stéphane Chazelas
sumber
Pertanyaan Shell: Saya rasa saya mengerti kode Anda dengan satu pengecualian. Ini -execberjalan shdengan satu perintah ( -c '...') dan {} +memberitahu untuk menempatkan lebih dari satu hasil ke perintah itu sekaligus. Yang tidak saya mengerti adalah mengapa ada shperintah lain setelah ini. Apa yang saya lewatkan?
Joe
2
@ Jo, itu yang masuk ke skrip inline $0. Artinya, itu memberi nama untuk skrip inline itu. Nama itu dapat digunakan dalam pesan kesalahan seperti <name>: fuser: command not foundmisalnya, jadi shumumnya merupakan pilihan yang baik dalam hal ini untuk memperjelas apa yang melaporkan pesan kesalahan itu (itu juga akan menjadi apa jika kita tidak memberikan argumen sama sekali setelah skrip inline).
Stéphane Chazelas