Verschieben Sie jede Datei, die kein Verzeichnis ist

14

Ich habe ein Verzeichnis, das ich versuche zu bereinigen, das sowohl Dateien als auch Unterverzeichnisse enthält. Was ich versuche, ist einfach: Alle Dateien in ein anderes Verzeichnis verschieben, aber alle Unterverzeichnisse so lassen, wie sie sind.

Ich denke etwas wie:

mv [*_but_no_dirs] ./other_directory

Es scheint, dass es eine einfache Möglichkeit geben sollte, dies mit Platzhaltern *und Regex zu tun ...

Hat jemand Ideen?

Fragezeichen
quelle
1
Verschieben Sie also alle Dateien in einen Unterordner, aber ignorieren Sie alle in den Unterverzeichnissen?
Wilf
@Wilf: Genau.
Questionmark
2
In zsh könnte man das mv **/*(.) ./other_directory- mit bash müsste man allerdings auf externe Befehle wie zurückgreifen find.
Godlygeek

Antworten:

12

Regex sind hier nicht beteiligt. Platzhalter in Bash (wie die meisten anderen Shells) stimmen nur mit Dateien überein, die auf den Dateinamen basieren, nicht auf dem Dateityp oder anderen Merkmalen. Es gibt eine Möglichkeit, nach Typ zu suchen: Durch Hinzufügen /am Ende des Musters werden nur Verzeichnisse oder symbolische Links zu Verzeichnissen gesucht. Auf diese Weise können Sie Verzeichnisse verschieben, dann verschieben, was übrig ist, und Verzeichnisse zurück verschieben - umständlich, aber es funktioniert.

tmp=$(TMPDIR=.. mktemp -d)
mv -- */ "$tmp"
mv -- * "$tmp"/other_directory/
mv "$tmp"/* .
rmdir "$tmp"

Eine Standardmethode zum Abgleichen von Dateien nach Typ ist das Aufrufen find.

find . -name . -o -type d -prune -o -exec sh -c 'mv "$@" "$0"' other_directory/ {} +

In zsh können Sie Glob-Qualifizierer verwenden , um Dateien nach Typ abzugleichen . Das .Qualifikationsmerkmal entspricht regulären Dateien. Verwenden Sie ^/diese Option, um alle Nicht-Verzeichnisse abzugleichen oder -^/auch symbolische Links zu Verzeichnissen einzuschließen.

mv -- *(.) other_directory/

In jeder Shell können Sie einfach eine Schleife ausführen.

for x in *; do
   if ! [ -d "$x" ]; then
     mv -- "$x" other_directory/
   fi
done
Gilles 'SO - hör auf böse zu sein'
quelle
8

Du könntest so etwas gebrauchen

find . -maxdepth 1 \( ! -type d \) -exec sh -c 'mv  "$@" MYDIR' _ {} \;

Zuerst findschauen wir nur innerhalb des aktuellen Verzeichnisses nach, dann ignorieren wir Verzeichnisse, indem ! -type d wir schließlich ausführen shund alles in das Zielverzeichnis verschieben. Sie könnten {} +am Ende versuchen, was schneller sein wird.

Valentin Bajrami
quelle
2
Ein bisschen Erklärung, bitte ...
Questionmark
1
@Questionmark Ich habe die Antwort aktualisiert und eine Erklärung hinzugefügt. Außerdem ist es ein Besuch wert mywiki.wooledge.org/UsingFind
Valentin Bajrami
Warum schlagen Sie -exec sh -c 'mv "$@" MYDIR' _ {} \;eher als vor -exec mv {} MYDIR \;? Nur um etwas zu bekommen, das durch Ändern der \;zu einem rationalisiert werden kann +? Das können Sie mit dem -exec mv -t MYDIR {} +Formular machen.
Scott
@Scott Ich hatte keine Ahnung von der -tFlagge. Ich habe auch in der Antwort erklärt, dass das +schneller ist, aber nicht alle findVersionen es unterstützen. Der obige Code ist also ziemlich kompatibel mit jeder verwendeten findShell.
Valentin Bajrami
1
@ val0x00ff: “… der obige Code ist ziemlich kompatibel mit jeder verwendeten findShell.” Richtig, aber so ist es find … -exec mv {} MYDIR \;und das verbraucht weniger Ressourcen als … -exec sh -c 'mv "$@" MYDIR' _ {} \;.
Scott
0

Es ist möglicherweise ein bisschen gefährlich, aber

cp * destination/
rm *

Da sowohl cp als auch rm keine Verzeichnisse ohne den Schalter -r bearbeiten.

miick
quelle
-1

Ich würde vorschlagen, einfach mv *.* destination/mit Ziel / als den Ordner zu tun , in den Sie verschieben.

Peter Z
quelle
2
check out: unix.stackexchange.com/help/formatting
Jeff Schaller
2
Verzeichnisnamen können 'Punkt' enthalten, und Dateinamen können dies ausschließen (und tun dies häufig). *.*Dadurch werden einige Verzeichnisse verschoben und einige Dateien belassen, was vom Fragesteller nicht gewünscht wird.
Dave_thompson_085
Sorry, aber das ist völlig falsch. Es bewegt einfach alles mit einem Punkt im Namen und nichts ohne einen Punkt. Punkte sind in keiner Weise exklusiv für Dateien und werden auch nicht von Dateien benötigt, sodass nur eine zufällige Auswahl von Dateien und Verzeichnissen verschoben wird.
Terdon
-2
mv $(ls -l | grep "^-" | awk '{print $9}') ./folder_where_move
sy s
quelle