Wie kann ich Dateien nach Dateierweiterung rekursiv kopieren und dabei die Verzeichnisstruktur beibehalten?

71

An der Linux-Befehlszeile möchte ich einen (sehr großen) Satz von .txtDateien von einem Verzeichnis (und seinen Unterverzeichnissen) in ein anderes kopieren .

Ich brauche die Verzeichnisstruktur, um intakt zu bleiben, und ich muss Dateien mit Ausnahme derjenigen, die auf enden, ignorieren .txt.

ungebrauchtes Gepäck
quelle
2
Wenn Sie cp und find als Tags in Ihrer Frage haben, bedeutet dies, dass Sie an diese Optionen gebunden sind? Da Ihr Datensatz sehr groß ist, ist es sinnvoll anzunehmen, dass der Kopiervorgang aus bestimmten Gründen unterbrochen werden kann und Sie ihn neu starten müssen. Ich bin nicht sicher, ob der find / cp-Ansatz die Übertragung fortsetzen und nur den fehlenden Teil kopieren kann. Wenn Sie nicht daran gebunden sind, / cp zu finden, können Sie rsync in Betracht ziehen, was intelligenter ist. Mit der Option --exclude können Sie TXT-Dateien überspringen.
Vtest
Fair Call - Rsync ist wahrscheinlich die bessere Option. Nicht gebunden zu finden / cp. (Ich habe sie trotzdem - rsync nicht auf dem Remote - Computer installiert wurde, war es ein Live - Web - Server und ich wollte so klein eines Fußabdruck wie möglich verlassen)
unclaimedbaggage

Antworten:

95

Hierfür können Sie find und cpio verwenden

cd /top/level/to/copy
find . -name '*.txt' | cpio -pdm /path/to/destdir

(-updm for overwrite destination content.)
Cedric
quelle
warum ich? Ich dachte, es ist nur um die Datei Änderungsdatum beizubehalten.
Mubashar
7
cd /source/path
find -type f -name \*.txt -exec install -D {} /dest/path/{} \;
sborsky
quelle
Sie vermissen ein .Nachher find. Auch auf macOS 10.13.1, dies gearbeitet:find . -type f -name "*.txt" -exec install -v {} /dest/path/{} \;
grimmig
2

Ein anderer Ansatz

find . -name '*.txt' -exec rsync -R {} path/to/dext \;

Marc
quelle
Ich mag diese Lösung. Früher find . -iname '*.txt' -exec rsync -Rptgon {} path/to/dext \;habe ich eine Übereinstimmung durchgeführt, bei der die Groß- und Kleinschreibung nicht berücksichtigt wurde, und die Eigentumsrechte und Berechtigungen beibehalten.
MountainX
1

Der einfachste Weg, der bei mir funktioniert hat:

cp --parents -R jobs/**/*.xml ./backup/

Ein Haken ist, dass Sie zu dem "gewünschten" Verzeichnis navigieren müssen, bevor der "übergeordnete Pfad" korrekt ist.

Stellen Sie außerdem sicher, dass Sie rekursive Globs in bash aktiviert haben:

shopt -s globstar
Icyerasor
quelle
1

Wie wäre es, wenn du es zuerst mit kopierst?

cp -r /old/folder /new/folder

dann gehe in den neuen Ordner und starte

find . -type f ! -iname "*.txt" -delete

oder nur

cp -r /old/folder /new/folder && find . -type f ! -iname "*.txt" -delete

Edit: ok du willst einen befehl der filtert (ich habe das nicht getestet weil mein system den cpiobefehl nicht hat !). Hier habe ich es gefunden: http://www.gnu.org/software/findutils/manual/html_mono/find.html#Copying-A-Subset-of-Files

find . -name "*.txt" -print0 |
     cpio -pmd0 /dest-dir

Bitte testen Sie dies zuerst, da ich es noch nicht ausprobiert habe. Wenn jemand das überprüfen würde, wäre das großartig.

Dennis
quelle
nickt Cheers - das würde funktionieren, aber ohne nach .txt zu filtern, schaue ich mir ein paar Millionen Dateien an (die mit ein paar hundert GB herauskommen). Wenn nötig, muss ich es vielleicht tun, aber ich würde gerne filtern, während ich kopiere, wenn möglich
nicht zurückgefordertes
1
Prost, bearbeitete Version funktioniert, wenn ich die '0' von -pmd0
nicht beanspruchtes
Sie sollten die halten 0in -pmd0und fügen Sie -print0am Ende des findBefehls (kurz vor dem |).
G-Man
1

Ich habe versucht, dasselbe unter macOS zu tun, aber keine der Optionen hat wirklich für mich funktioniert. Bis ich entdeckt habe ditto.

Ich musste viele .wav-Dateien kopieren und sie überspringen lassen.

find . -type f -iname "*.wav" -ls -exec ditto {} /destination/folder/{} \;

  • find .- Läuft im aktuellen Ordner zu finden. Stellen Sie sicher, cd /source/folderbevor Sie beginnen

  • -type f - Legt fest, dass nur nach Dateien gesucht wird

  • -iname "*.wav" - Dies weist es an, nach Groß- und Kleinschreibung zu suchen * .wav
  • -ls- Hier sehen Sie die Datei, an der gearbeitet wird. Sonst zeigt es nichts.
  • -exec ditto {} /destination/folder/{} \; - Kopiert und erstellt alle Dateien mit demselben Verzeichnisbaum.
Benjamin McGuire
quelle
0

Zum Verzeichnis navigieren:

find . -regex '<regexp_to_get_directories_and_files_you_want>' | xargs -i cp -r --parents {} path/to/destination

Es ist ein bisschen direkter und mächtiger, wenn Sie reguläre Ausdrücke verwalten.

Keywalker
quelle
-1

Zum Verzeichnis navigieren:

cp '*.css' /path/to/destination

Sie müssen zu jedem Ordner im Verzeichnis navigieren, aber dies ist besser als die meisten Optionen, die ich bisher gesehen habe.

Phönix
quelle
Diese Methode ist nicht rekursiv, was bedeutet, dass Sie dies für große Verzeichnisse für eine Weile tun könnten ...
Iain Reid