So verschieben Sie alle Dateien in aktuellen Unterordnern nach oben

8

Ich habe 50 Ordner mit einigen Unterordnern, mit insgesamt mehr als 1000 Audiodateien. Ich muss alle Unterordner entfernen und alle Dateien auf die aktuelle Ebene bringen. Versucht, mv */* ./aber es beschwert sich: Argumentliste zu lang

Pedro Gonzalez
quelle

Antworten:

7

Ich gehe davon aus, dass Ihre Audiodateierweiterung .mp3 ist

find <AudioFolderPath> -name '*.mp3' -exec mv -it <YourTargetFolder> {} +

Anmerkungen:

  • Ersetzen Sie .mp3durch die Erweiterung Ihrer Audiodateien

  • Ersetzen Sie <AudioParentFolderPath>durch den übergeordneten Ordner, der Ihre Unterordner enthält.

  • Ersetzen Sie ihn <YourTargetFolder>durch den Ordnerpfad, in den Sie alle Dateien ablegen möchten .

  • Wenn zwei Dateien aus verschiedenen Unterordnern denselben Namen haben, wird nur eine verschoben.

Bearbeiten: Wie Costas sagte: "Der -iSchalter macht mvinteraktiv, er wird aufgefordert, bevor vorhandene Dateien überschrieben werden."

Muhammad
quelle
Können Sie mit '-t' zuerst das Ziel angeben? (Da ich diese Option hier nicht auf meinem "mv" habe, kann ich nur davon ausgehen, dass Sie zuerst den Zielordner und dann die Liste der Dateien verschieben, die dorthin verschoben werden sollen ... aber wenn nicht, wird dies versuchen, alle zu passen im letzten Dateinamen, eine Warnung ausgeben) tkönnte für "Ziel" sein?
Olivier Dulac
Ja, wie Sie sagten, -terlauben Sie, zuerst das Ziel anzugeben. von der mvHandbuchseite: -t, --target-directory=DIRECTORY move all SOURCE arguments into DIRECTORY
Muhammad
1
Bitte beachten Sie, dass dies die Option von GNU mv ist und nicht auf allen Unices verfügbar ist (zumindest in einigen Produktionsumgebungen). Ich biete eine portablere Lösung an, aber Ihre funktioniert gut für Linux
Olivier Dulac
ja @OlivierDulac, du hast recht, danke für deinen Hinweis.
Muhammad
4
find . -type f -mindepth 2 -exec mv -t ./ {} +

Beachten Sie, dass dieser Befehl alle Dateien mit demselben Namen überschreibt. Sie können dies verwenden, um vor dem Überschreiben aufgefordert zu werden:

find . -type f -mindepth 2 -exec mv -it ./ {} +

Erläuterung

  • -type f : finde nur reguläre Dateien.
  • -mindepth 2 : finde nur Dateien in Unterverzeichnissen.
  • -exec mv -it ./ {}: -execbedeutet "diesen Befehl für jede gefundene Datei ausführen ". Das {}wird durch die Dateinamen ersetzt. Der -iSwitch macht mvinteraktiv, fordert vor dem Überschreiben vorhandener Dateien auf und -tsetzt das Zielverzeichnis auf ./.
  • +: (In einem Argument Zeile) setzen Dateien zusammen können so viele wie Shell mit betreiben Befehl aufzurufen Befehl Mindestzeiten (nicht eins nach dem anderen , sondern eine bis mehrere).

In Bezug auf weitere Löschungen leerer Ordner können Sie dasselbe Rezept verwenden:

find . -type d -empty -delete
Costas
quelle
1
-type fWählt nur einfache Dateien aus, ausgenommen symbolische Links, Named Pipes und dergleichen. Sie können alle Dateien außer Verzeichnissen verschieben ! -type d.
Jimmy
@jimmij Ich nehme an, niemand speichert Audiodateien als Named Pipe oder etwas anderes. Wenn Sie sich über Symlinks Gedanken machen, können Sie den -LParameter
Costas
1
-iist Standard, -tist nur GNU (nichts mit Linux zu tun, das nur ein Kernel ist, der in einigen GNU- und Nicht-GNU-Systemen zu finden ist)
Stéphane Chazelas
Ich stimme @ StéphaneChazelas zu: -texistiert auf einigen Systemen nicht (wie einem nicht so alten AIX)
Olivier Dulac
@OlivierDulac Es ist fast unmöglich, eine Entscheidung zu finden, um alle zufrieden zu stellen, daher sind die verschiedenen Varianten willkommen. Niemand verbietet Ihnen, die Zeichenfolge zu ändernfind . -type f -mindepth 2 -exec mv {} ./ \;
Costas
2

Ja, dies ist eine Begrenzung der kumulierten Größe von Argumenten und Umgebungen, die execve()beim Ausführen eines externen Befehls an den Systemaufruf übergeben werden.

Mit zshkönnen Sie mvstattdessen das eingebaute verwenden:

zmodload -F zsh/files +b:zf_mv
zf_mv ./*/* .

Oder verwenden Sie zargs, um die Liste in überschaubare Teile zu unterteilen:

autoload zargs
zargs -Ifiles ./*/* -- mv files .

Mit ksh93:

command -x mv ./*/* .

Mit GNU xargsund mit GNU mvmit einer Shell, in printfdie eingebaut ist (die meisten mkshsind die bemerkenswerte Ausnahme):

printf '%s\0' ./*/* | xargs -r0 mv -t .
Stéphane Chazelas
quelle
Beachten Sie bitte, dass OP nur Dateien und keine Verzeichnisse verschieben möchte. Sie müssen sich also darum kümmern. Für den zshFall, dass Sie einige Glob-Qualifikationsmerkmale setzen können , z . B. (.)oder (^/)nach dem letzten *.
Jimmy
0

Eine ziemlich tragbare Lösung könnte sein:

Suchen Sie alle Dateien in jedem Unterordner und verschieben Sie sie in das aktuelle Verzeichnis

find ./*/ -type f -print | xargs mv -i "{}" ./

Sie können ein | egrep "\.au$|\.mp3$|\.ac3$"Dazwischen hinzufügen, um sicherzustellen, dass es sich bei den gefundenen Dateien um Dateien mit einer Audioerweiterung handelt (fügen Sie so viele Erweiterungen hinzu, wie für alle Typen erforderlich sind. Ich stelle nur drei häufig verwendete Dateien zur Verfügung.)

Olivier Dulac
quelle
In Ihrem Fall müssen Sie findüberhaupt nicht anrufen . Gerade genug echooderprintf
Costas
@Costas: Das OP erwähnt, dass es so viele Dateien gibt, dass "*" nicht erweitert werden kann ... Hier erweitere ich nur die 50 Ordnernamen, und der Rest wird von xargs
Olivier Dulac
Aber findlösen Sie das Problem nicht, sondern xargstun Sie es.
Costas