Come copiare tutti i file in una cartella esclusi i file che vengono scritti?


12

Scarica più file in una cartella downloadingtramite HTTPie . Uno script bash ha lo scopo di elaborare i file scaricati e ho provato a copiare i file scaricati in un'altra cartella come

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

ma questo copia anche i file, che non sono ancora stati completati. Ho provato a limitare il trasferimento a file più vecchi aggiungendo -mmin +5al comando. Qual è il comando efficiente per lasciare che i file vengano scritti e trasferire solo i file scaricati?


Se si esegue la copia nello stesso filesystem e si imposta il downloader in modo da non rinominarlo (scaricare per %.partrinominarlo in%). Quindi se il downloader si comporta bene (non fa altro), dovresti essere in grado di rinominare i mvfile ( ).
ctrl-alt-delor,

1
Che tipo di elaborazione stai cercando di fare? Molto probabilmente è disponibile un'opzione molto più semplice, come l'uso di una pipeline.
gardenhead,

Risposte:


11

Non molto efficiente, ma potresti fare:

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

Questo è verificare che il file non è elencato con un writo amodalità ccesso nel lI st di openna files prima mo ving.

L' psmiscimplementazione di fusercome si trova tipicamente sui sistemi operativi basati su Linux ha una -wfunzione (per verificare la presenza di file aperti per la scrittura) ma sfortunatamente funziona solo -kper uccidere i processi corrispondenti. Tuttavia, sembra che tu possa ancora usarlo usando lo pseudo-segnale 0 che non fa nulla:

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

Rimuovere -s(o addirittura sostituirlo con -v) se si desidera vedere quali processi impediscono lo spostamento.

Nota che se non esegui questi comandi come superutente, otterrai solo informazioni sui tuoi processi. Se i processi di download dei file sono in esecuzione come utente diverso, rimarranno inosservati.

Si noti inoltre che, a meno che non si stiano spostando i file in un file system diverso, lo spostamento dei file non impedirà a qualsiasi processo che sta scrivendo sul file di finire di scriverlo.

Tuttavia, a seconda di quello che sono stati progettati per fare in seguito, potrebbero essere confuse se al termine della scrittura, il file non è più lì (ad esempio, se vogliono cambiare alcuni attributi del file dopo il download e così fanno non tramite il descrittore di file (come chmod()vs fchmod(), o utimes()che non può essere fatto tramite un descrittore di file)).


Domanda Shell: penso di aver compreso il tuo codice con una sola eccezione. È in -execesecuzione shcon un comando ( -c '...') e gli {} +dice di inserire più di un risultato in quel comando alla volta. Quello che non capisco è perché c'è un altro shdopo il comando. Cosa mi sto perdendo?
Joe

2
@Joe, questo è ciò che accade nello script inline $0. Cioè, dà un nome a quello script in linea. Quel nome può essere usato in messaggi di errore come <name>: fuser: command not foundad esempio, quindi shè generalmente una buona scelta in questo caso per chiarire cosa sta segnalando quel messaggio di errore (è anche quello che sarebbe se non avessimo dato alcun argomento dopo il inline-script).
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.