Wie kopiere ich alle Dateien in einen Ordner mit Ausnahme der zu schreibenden Dateien?

12

Ich lade mehrere Dateien downloadingüber HTTPie in einen Ordner herunter . Ein Bash-Skript zielt darauf ab, heruntergeladene Dateien zu verarbeiten, und ich habe versucht, die heruntergeladenen Dateien in einen anderen Ordner als zu kopieren

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

Dies kopiert aber auch die Dateien, die noch nicht fertig sind. Ich habe versucht, die Übertragung auf ältere Dateien zu beschränken, indem ich -mmin +5sie dem Befehl hinzufügte . Was ist der effiziente Befehl, um die Dateien, die gerade geschrieben werden, zu belassen und nur heruntergeladene Dateien zu übertragen?

Googlebot
quelle
Wenn Sie in dasselbe Dateisystem kopieren und den Downloader so einstellen, dass er nicht umbenannt wird (download to %.partthen rename to%). Wenn sich der Downloader dann gut benimmt (macht nichts Ungewöhnliches), sollten Sie in der Lage sein, ( mv) Dateien umzubenennen .
ctrl-alt-delor
1
Welche Art von Verarbeitung versuchen Sie zu tun? Es gibt höchstwahrscheinlich eine viel einfachere Option, wie die Verwendung einer Pipeline.
Gardenhead

Antworten:

11

Nicht sehr effizient, aber Sie könnten Folgendes tun:

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

Das ist zu prüfen, ob die Datei nicht mit aufgeführt ist wRitus access - Modus in der li st von oStift files vor mo ving.

Die psmiscImplementierung von fuserwie bei Linux-basierten Betriebssystemen üblich hat eine -wFunktion (nach zum Schreiben geöffneten Dateien suchen), funktioniert aber leider nur -k, um die entsprechenden Prozesse abzubrechen. Es scheint jedoch, dass Sie es weiterhin verwenden können, indem Sie das Pseudosignal 0 verwenden, das nichts bewirkt:

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

Entfernen Sie das Element -s(oder ersetzen Sie es durch -v), wenn Sie sehen möchten, welche Prozesse das Verschieben verhindern.

Beachten Sie, dass Sie nur Informationen zu Ihren Prozessen erhalten, wenn Sie diese Befehle nicht als Superuser ausführen. Wenn die Prozesse zum Herunterladen der Dateien als ein anderer Benutzer ausgeführt werden, bleiben sie unentdeckt.

Beachten Sie auch, dass das Verschieben der Dateien nicht den Abschluss des Schreibvorgangs in die Datei verhindert, es sei denn, Sie verschieben die Dateien in ein anderes Dateisystem.

Abhängig davon, wofür sie später entwickelt wurden, können sie jedoch verwirrt sein, wenn die Datei nach dem Schreiben nicht mehr vorhanden ist (z. B. wenn sie nach dem Herunterladen einige Attribute der Datei ändern möchten und dies nicht über den Dateideskriptor (wie chmod()vs fchmod()oder utimes()nicht über einen Dateideskriptor)).

Stéphane Chazelas
quelle
Shell-Frage: Ich glaube, ich verstehe Ihren Code mit einer Ausnahme. Die -execwird shmit einem Befehl ( -c '...') ausgeführt und {} +weist sie an, mehr als ein Ergebnis gleichzeitig in diesen Befehl einzugeben. Was ich nicht verstehe, ist, warum es shnach dem Befehl einen anderen gibt . Was vermisse ich?
Joe
2
@Joe, das geht in die Inline-Skripte $0. Das heißt, es gibt diesem Inline-Skript einen Namen . Dieser Name kann in Fehlermeldungen wie verwendet wird , <name>: fuser: command not foundzum Beispiel, so shist in der Regel eine gute Wahl in diesem Fall deutlich zu machen , was die Fehlermeldung berichtet (das ist auch das, was es wäre, wenn wir überhaupt nicht gegeben haben jedes Argument nach dem Inline-Skript).
Stéphane Chazelas