Kopieren Sie Dateien von einem Ordner in einen anderen, aber zwischen den einzelnen Dateien liegt ein Intervall

7

Gibt es eine Möglichkeit, Dateien von Ordner a nach Ordner b zu kopieren, aber der Prozess zwischen den einzelnen Dateien für eine Sekunde unterbrochen zu werden? Ich möchte eine ganze Reihe von Dateien in einen Überwachungsordner kopieren, aber ich weiß aus Erfahrung, dass wenn ich alle auf einmal kopiere (entweder über Terminal-CP oder GUI), mein Torrent abstürzt ... Wenn ich die Dateien kopieren könnte mit einem zweiten Intervall zwischen ihnen würde das rtorrent die Zeit geben, Dinge zu erledigen. Wenn ich das mit einem Befehl tun könnte, würde mich das davon abhalten, es einzeln manuell zu tun.

zotteken
quelle

Antworten:

10

Einzelbefehlslösungen

Unter vielen Optionen, einschließlich Schleifen, die cpund verwenden sleep, könnten wir uns für findzwei -execFlags entscheiden, um genau diese Befehle auszuführen.

find ~/dir_1/ -type f -maxdepth 1  -exec cp {} ~/dir_2 \;  -exec sleep 1   \;

Hier sind die Optionen:

  • ~/dir_1, das Ursprungsverzeichnis, über das findfunktioniert.
  • -type f Holen Sie sich nur Dateien
  • -maxdepth 1im Verzeichnisbaum maximal 1 Ebene nach unten absteigen; verhindert das Absteigen in Unterverzeichnisse
  • -exec cp {} ~/dir_2 \;Kopieren Sie die aktuell verarbeitete Datei, die durch den {}Parameter festgelegt wurde, nach ~/dir_2. Das \;bezeichnet cpdie Verarbeitung einer einzelnen Datei gleichzeitig, anstatt so viele Dateien wie möglich in die Datei zu stecken {}. Der Backslash-In \;ist erforderlich, um zu verhindern, dass die Shell diesen als Befehlsabschluss falsch interpretiert.
  • exec sleep 1 \;wird für sleep 1jede aktuelle Datei ausgeführt.

Wenn Sie eine Liste von Dateien in einer Datei haben, können Sie Folgendes tun:

xargs -I % --arg-file=input.txt sh -c 'cp % ~/dir_2/ ;sleep 1'

Optionen hier sind:

  • -I % bezeichnet das Symbol, das sich auf die Datei innerhalb des Befehls bezieht
  • --arg-file=input.txt Lesen Sie die zu befehlenden Argumente aus einer bestimmten Datei
  • sh -c 'cp % ~/dir_2/ ;sleep 1'/bin/shmit bereitgestellten Befehlen per -c '...'Flag ausführen ; %wird durch Dateinamen ersetzt.

Schleifenlösungen

Sie könnten zum Beispiel eine for-Schleife verwenden

for f in "/path/to/folder_1"/*; do
    cp "$f"  "/path/to/folder_2/"
    sleep 1
done

Aus Gründen der Übersichtlichkeit ist dies in mehreren Zeilen formatiert, dies funktioniert jedoch genauso gut als einzelne Zeile. Sie können dies auch in eine Funktion verwandeln:

delaycp(){
    for f in "$1"/*; do
        cp "$f"  "$2"/
        sleep 1
    done
}

Und benutze es als

delaycp "/path/to/folder1" "/path/to/folder2"

Wenn Sie alternativ nur bestimmte Dateien kopieren möchten, nicht alles, was *Glob im Verzeichnis erfasst, können Sie auch die Pfadnamenerweiterung verwenden, etwa eine file{1..25}oder eine Eingabetextdatei wie diese input.txt:

/path/to/folder_1/file1
/path/to/folder_1/file2
/path/to/folder_1/file3

Und von dort aus nutzen Sie die while IFS= read -r lineStruktur, um die Datei zu lesen:

while IFS= read -r line || [ -n "$line" ]; do
    cp "$line" "/path/to/folder_2/${line##*/}"
    sleep 1
done < input.txt
Sergiy Kolodyazhnyy
quelle
Was soll die "oder" -Klausel in Ihrer whileSchleife tun?
Bis auf weiteres angehalten.
2
@DennisWilliamson Zusätzlicher Schutz für den Fall, dass die Datei nicht in \nNewline endet. Erstellen Sie diese Datei als Beispiel : printf "Line one\nLine two" > input.txt. Die while-Schleife ohne diese oder Klausel wird nur erhalten Line one. Warum ? Weil "read" eingebaut nur dann Erfolg bringt, wenn die Zeile mit endet \n. Das Line twowird immer noch in der lineVariablen landen , aber readden Fail-Exit-Status zurückgeben. Deshalb brauchen wir eine zusätzliche Prüfung, falls die Variable nicht leer ist.
Sergiy Kolodyazhnyy
In Ihrer Erklärung für die findLösung sollte das erste Argument ~/dir_1anstelle von sein ~/dir_2. Der ganze Befehl ist korrekt, nur die Erklärung nicht.
Lienhart Woitok
2

Mit parallel

Hier ist eine parallel Parallel installierenLösung, geben Sie die Argumente parallelmit :::genau wie mit cpoder verwenden Sie eine Dateiliste:

parallel -j1 'cp {} /path/to/dir2/;sleep 1' ::: /path/to/dir1/* # or
parallel -j1 'cp {} /path/to/dir2/;sleep 1' :::: /path/to/file_list.txt

Die -jOption weist parallelan, dass nur 1Jobs gleichzeitig ausgeführt werden sollen, anstatt Jobs parallel auszuführen. Die einfachen Anführungszeichen enthalten lediglich das Skript, in dem {}die aktuell verarbeitete Datei ersetzt wird, und / :::oder ::::führen die Argumentliste bzw. die Argumentdatei (en) ein. Sehen Sie man parallelfür viel mehr.

Mit find -exec

findbietet eine bequeme Möglichkeit, Befehle für die Ergebnisse auszuführen, z. B. um jede .logDatei in und unter das aktuelle Verzeichnis zu kopieren.

find -name "*.log" -exec sh -c 'cp "$0" /path/to/dir2/;sleep 1' "{}" \;
Dessert
quelle