Wie kann ich alle Dateien in Unterverzeichnissen rekursiv in ein einzelnes Verzeichnis verschieben?


10

Ich versuche, alle Dateien im aktuellen Verzeichnis und alle Unterverzeichnisse in einem Verzeichnis zu sammeln. Ich versuche so etwas wie das Folgende

find -type f -exec mv {} collection/{} \; 

Der obige Befehl funktioniert nicht, da der zweite {}den vollständigen Pfad angibt. Wie kann ich alle Dateien sammeln?

Antworten:


14

Wenn Sie das {}von entfernen mv, mvwird es als Zielverzeichnis verwendet, wobei alle übergeordneten Verzeichnisse ignoriert werden:

find -type f -exec mv {} collection/ \;

ohh das ist mir nicht eingefallen. danke :)
Bunny Rabbit

Wie ich in meiner Antwort auf die Frage sage, ist dies möglicherweise eine schlechte Idee. Vielleicht -maxdepth 1würde es helfen , das Argument zu verwenden.
Loevborg

Kommen Sie und denken Sie darüber nach, es scheint, als hätte ich Ihre Frage falsch gelesen :) Entschuldigung.
Loevborg

@loevborg: Ich habe dem Titel jetzt "rekursiv" hinzugefügt. Wenn es immer noch Verwirrung gibt, bearbeiten Sie es bitte und verbessern Sie es :)
Lekensteyn

1
Eine schnellere Variante dieser Antwort istfind -type f -print0|xargs -0r mv -it colection/
hildred

5

Anstatt zu verwenden find(was die Arbeit gut macht), können Sie auch die Shell zu diesem Zweck verwenden.

Angenommen, Sie möchten alle Dateien von $ PWD bis $ DEST. Der natürliche Versuch wäre:

mv $PWD/* $DEST

Wie funktioniert das? Der Ausdruck "$ PWD / *" wird auf die Namen aller Dateien in diesem Verzeichnis erweitert. Diese Shell-Funktion wird als "Globbing" bezeichnet. Das letzte Argument von mvist das Zielverzeichnis. Wenn Sie sehr viele Dateien haben, funktioniert dies nicht, da die Länge der Befehlszeile begrenzt ist.

Die Lösung hat jedoch das Problem, dass Punktdateien weggelassen werden - oder "versteckte" Dateien, Dateien und Verzeichnisse, deren Name mit einem "." Beginnt. Um dies zu lösen, müssen Sie Ihre Shell anweisen, beim Globbing Dotfiles einzuschließen. Verwenden Sie dazu

shopt -s dotglob

bei der Verwendung bash(und Sie verwenden wahrscheinlich, es bashsei denn, Sie haben die Standardeinstellung geändert). In dieser Shell funktioniert der obige Befehl auch für Punktedateien.

Im zshÜbrigen haben Sie die Möglichkeit, dies von Fall zu Fall zu wählen. Um dies zu tun, setzen Sie

setopt extendedglob

in deinem .zshrc. Dann können Sie verwenden

mv $PWD/*(D) $DEST

um alle Dateien einschließlich der Punktedateien zu verschieben. (Das "D" bewirkt, dass die Option "GLOB_DOTS" vorübergehend aktiviert wird.)

Die ursprüngliche Frage war nun, alle regulären Dateien (nicht Verzeichnisse) aus allen Unterverzeichnissen und ihren Unterverzeichnissen in ein einziges Verzeichnis zu verschieben. Dies kann erreicht werden mit zsh:

mv $PWD/**/*(D.)

Hier lässt der Ausdruck **/*den Globber rekursiv in Unterverzeichnisse absteigen. Das Dbedeutet "auch Punktdateien auswählen"; das .Mittel "nur reguläre Dateien auswählen, keine Verzeichnisse".


Nun, ich wollte auch in alle Unterverzeichnisse zurückkehren, aber dank der Informationen, die nützlich sind, stoße ich auch oft auf diese Situation :)
Bunny Rabbit

Tatsächlich ist find kein Overkill dafür. Globbing wählt alle Übereinstimmungen aus, nicht nur Dateien, sondern auch Verzeichnisse. Wenn Sie sich Sorgen um die Leistung machen, können Sie auch Folgendes verwenden : find -type f -exec mv -t collection/ {} +. Informationen zur Funktionsweise finden Sie auf der Handbuchseite.
Lekensteyn

Lekensteyn, du hast recht. Ich habe die Antwort jetzt aktualisiert, da ich die Frage verstanden habe.
Loevborg

2
Wunderbare Antwort, schade, dass es für die Frage nicht besonders relevant ist :).
crazy2be
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.