Linux (MV oder CP) spezifische Dateien aus einer Textliste von Dateien?


34

Ich habe ein Verzeichnis mit vielen Dateien, etwa 50.000 PDFs und anderen Dateien auf einem Server. Ich muss bestimmte in ein anderes Verzeichnis verschieben. Ich kann eine Liste der Dateien erstellen, die entweder in csv oder einem anderen Textformat verschoben werden müssen.

Ich muss lediglich ein Bash-Skript ausführen und die in der Textdatei aufgelisteten Dateien in ein anderes Verzeichnis verschieben oder kopieren.

Gibt es eine einfache Möglichkeit, dies zu tun? Anregungen oder Ressourcen wäre sehr dankbar.


Außerdem werden die Dateien beim Hinzufügen zum Verzeichnis nach dem Zufallsprinzip benannt. Es gibt keine Namenskonvention oder Logik, mit der bestimmte Dateien verschoben werden könnten.
Jestep

Antworten:


26

rsync hat mehrere Optionen , die eine Liste von Dateien zu verarbeiten nehmen können ( --files-from, --include-fromusw.).

Zum Beispiel wird dies den Trick machen:

rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory

2
Beispiel:rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory
anneb 31.10.18

28

Um eine nutzlose Verwendung von cat(und wenn Sie nicht verwenden rsync) zu vermeiden :

xargs -a file_list.txt mv -t /path/to/dest

Dies behandelt jeden gültigen Dateinamen, es sei denn, er enthält eine neue Zeile, wenn die Dateien in einer Zeile aufgelistet sind.


2
Ein Nachteil dieses Ansatzes ist, dass, wenn die Dateien in der Liste Pfadnamen enthalten (dh sie befinden sich nicht alle im selben Verzeichnis), die Verwendung von mvalle in dasselbe Zielverzeichnis reduziert. Der rsyncAnsatz in der akzeptierten Antwort leidet nicht unter dieser Einschränkung.
Jason R

Außerdem habe ich diesen Befehl ausprobiert und xargs brach bei allen Dateien ab, die ein einfaches Anführungszeichen enthielten ("unvergleichliches einfaches Anführungszeichen")
James Beninger

Das hat bei mir funktioniert, weil ich eigentlich die Dateien von verschiedenen Quellpfaden im selben Zielverzeichnis haben wollte.
PseudoNoise

15
for file in `cat listoffiles`; do mv "$file" /path/of/destination ; done

vorausgesetzt, Bash plus listoffileseine Datei pro Zeile. Mein einziger Einwand gegen die Rsync-Route ist, dass das OP nach einer Methode zum Verschieben der Dateien fragt, nicht zum Kopieren. rsync hat mehr Flags als eine königliche Hochzeit, daher bin ich mir sicher, dass es weiter modifiziert werden kann, aber manchmal ist einfacher besser!


1
Diese Lösung scheint mir die flexibelste zu sein. Ich habe es letztendlich mit rsync anstelle von cp oder mv verwendet, nur weil ich die Option für relative Dateipfade brauchte.
Spamwich

4
Nizza, nur ich hatte Probleme mit Leerzeichen, so dass ich es geändert:while read -r file; do mv "$file" /path/of/destination ; done < listoffiles
user1182474

1
@ user1182474 Danke und eine elegante Verwendung der Eingabeumleitung. Die traditionelle Methode, Zufriedenheit mit einer Antwort zu zeigen, ist übrigens, zu stimmen!
MadHatter unterstützt Monica

1
@ user1182474 danke dafür! Der letzte Schritt in vielen Modifikationen musste etwas blind gemacht werden, um meine OSX-Backup-Utilities auf mein Android zu portieren!
Charlie Gorichanaz

4

Dies hängt vom Format der von Ihnen verwendeten Textdatei ab. Beispiel: Sie haben die Liste der Dateien so geschrieben, dass sich jede Datei in einer neuen Zeile befindet. Sie können Xargs wie folgt verwenden:

$ cat your_text_file | xargs cp -t /path/to/destination

Sie können auch den findBefehl mit der -execOption verwenden. Dateien kopieren / verschieben.


3
rsync --files-from=file_list.txt /path/to/source/ /path/to/dest/

Rsync bietet gegenüber den Befehlen cpoder den zusätzlichen Vorteil, mvdass Ordner automatisch erstellt werden, wenn sie nicht vorhanden sind.


Warum wird es /path/to/sourcebenötigt, wenn die Pfade aus der Dateiliste übernommen werden?
bzero

@bzero vielleicht Liste von Dateien kann relative Pfade enthalten?
DreadfulWeather

2

Ich denke, die Antwort von rsync ist besser, aber nur für eine andere Option:

tar -cf - -T FILE_OF_FILENAMES_TO_MOVE.txt |(cd /path/to/new/dir && tar -xvf -)

Dies ist gut für eine Docker-Datei, da tar im Ubuntu-Basis-Image verfügbar ist, aber nicht rsync.
Kristianp

1

Ich habe versehentlich den gesamten Inhalt eines Verzeichnisses in ein Zielverzeichnis kopiert, anstatt das gesamte Verzeichnis zu verschieben. Dies führte dazu, dass ein überfülltes Zielverzeichnis anstelle des Ursprungsverzeichnisses zum Verzeichnis hinzugefügt wurde.

Um dies zu beheben, habe ich Folgendes getan:

ls -rt /path/to/cluttered/destination/directory/ > /opt/dircheck/filestomove Mit dem obigen Befehl wird die Datei filestomove erstellt, die eine Liste aller Inhalte des Zielverzeichnisses enthält, und zwar in umgekehrter Reihenfolge nach der Zeit, dh vom ältesten zum neuesten.

Dann habe ich ein Unterverzeichnis des jetzt überfüllten Zielverzeichnisses erstellt, in das das Zeug verschoben werden soll.

mkdir /path/to/cluttered/destination/directory/newsubdirectory

Dann wiederholte ich die Verzeichnisliste, mit Ausnahme der Auflistung auf dem Bildschirm und der Anzeige weiterer Details.

ls -lrht /path/to/cluttered/destination/directory/ Diese Zeile listet das Verzeichnis auf, sortiert nach aufsteigendem Datum (umgekehrte Sortierung nach Uhrzeit), und zeigt weitere Informationen an, einschließlich des Datums- / Zeitstempels jeder Datei im jetzt überfüllten Zielverzeichnis. Ich beziehe mich darauf und beginne oben, um zu zeigen, welche Verzeichnisse und Dateien ich dort behalten möchte, wo sie waren. Es wird eine Lücke im Datums- / Zeitstempel der Dateien geben, in der alle neuen Dateien beginnen, die nicht vorhanden sein sollten.

Dann habe ich die im ersten Schritt oben erstellte Datei filestomove bearbeitet (die nach Datum sortiert ist) und die wenigen Dateien aus der Liste gelöscht, die zuvor dort vorhanden waren und die ich aus dem ursprünglichen Verzeichnis behalten möchte.

vim /opt/dircheck/filestomove Löschen Sie von oben alle Dateien, die Sie nicht verschieben möchten.

Dann habe ich den zuvor in diesem Beitrag aufgeführten Befehl verwendet, um die Dateien in meiner Liste in das neue Verzeichnis zu verschieben, das ich erstellt habe.

sudo xargs -a /opt/dircheck/filestomove mv -t /path/to/cluttered/destination/directory/newsubdirectory

Dadurch wurden alle Dateien im Bruchteil einer Sekunde verschoben. (Hinweis: Möglicherweise benötigen Sie das sudo am Anfang nicht. Dies ist eine Frage der Dateiberechtigungen.)

Jetzt ist mein ursprüngliches Zielverzeichnis schön sauber und enthält ein neues Verzeichnis mit allen Dateien und Verzeichnissen, die es überfüllt haben.


1

Wenn (und nur wenn), haben Sie keine unangenehmen Zeichen in den Dateinamen (Leerzeichen, Zeilenumbrüche, die xargs verwirren würden, wie Dinge in einzelne Argumente aufgeteilt werden), und Sie generieren eine Liste von Dateien, die durch Zeilenumbrüche voneinander getrennt sind (eine Datei) pro zeile) könnte man sowas machen.

cat filenames.txt | xargs mv -t /path/to/move/files/to

(Im Allgemeinen, siehe man xargs , es ist super)

Wenn Ihr bestimmter MV nicht die Option -t hat, können Sie auch einige Tricks wie ausführen

( cat filenames.txt; echo; echo /path/to/move/files/to ) | xargs mv

Hinweis - Keiner dieser Befehle funktioniert wie erwartet, wenn Dateinamen mit Zeilenumbrüchen enthalten sind.


Jedoch; Siehe Ignacios Antwort, rsync ist irgendwie für dieses Zeug gemacht.
Kjetil Joergensen

cp, mvund dergleichen haben keine -tOption auf bsd 's, und das zweite Beispiel mit Subshell hat bei mir nicht funktioniert ( /path/to/movewird als letzter Dateiname angehängt)

1
@ w17t - hört sich so an, als würde die Datei filenames.txt nicht mit einer neuen Zeile enden. Fügen Sie entweder eine neue Zeile am Ende der Datei filenames.txt hinzu oder tun Sie etwas wie(cat filenames.txt; echo; echo /path/to/move/files/to) | xargs mv
Kjetil Joergensen

0

Versuchen Sie etwas wie:

cat list.txt | while read line; do mv "$line" /images; done

könnte while read line; do mv $line /images; done < list.txt als ein einziger Befehl gewesen sein
Ignivs

0

Das Folgende funktionierte für mich, als ich alle PNG-Dateien von einem bestimmten Pfad (und allen Unterverzeichnissen) an einen neuen Speicherort kopieren musste, während die Verzeichnisstruktur beibehalten wurde:

rsync -av --prune-empty-dirs --include='*/' --include='*.png' --exclude='*' source/ destination/

Da RSYNC zuerst den Spiegel der Verzeichnisstruktur erstellt und dann die Dateien synchronisiert, können Sie überschüssige Ordner finden, die leer sind. Ich habe das Flag --prune-empty-dirs verwendet, um diese leeren Verzeichnisse zu entfernen.

Ich habe keine Zugehörigkeit, hielt es aber für richtig, der Quelle, die diese Lösung inspiriert hat, Anerkennung zu zollen : http://techblog.zabuchy.net/2011/transfer-only-selected-file-types-with-rsync/

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.