Bash-Snippet, um alle Dateien in einem Verzeichnis in dieses Verzeichnis zu verschieben

14

Ich habe ein Verzeichnis mit vielen Dateien und Verzeichnissen. Um es aufzuräumen, werde ich all diese Dateien in ein Verzeichnis legen, also würde ich so etwas tun:

$ ls | wc -l
123
$ mkdir new_directory
$ mv * ./new_directory

Aber das wird natürlich nicht funktionieren , weil dann wird es versuchen , sich zu bewegen new_directoryin new_directory. Gibt es eine einfache Möglichkeit, in einer Zeile das zu tun, was ich will, ohne dass ich alle Dateien und Verzeichnisse in diesem Verzeichnis kopieren und einfügen muss?

Rory
quelle
3
es funktioniert, es wird nur eine Fehlermeldung ausgegeben, dass das neue_Verzeichnis nicht in sich selbst verschoben werden kann.
cas

Antworten:

18

Ihre

mv * ./new_directory
Befehl wird tatsächlich funktionieren; Es wird nur eine Warnung ausgegeben, dass das Verzeichnis nicht in sich selbst verschoben werden kann.

mibus
quelle
Das "einzige" Problem dabei ist, dass, wenn die gesamte Erweiterung des Befehls zu lang wird (dh zu viele Dateien, zu lange Namen), dies nicht mehr funktioniert.
Niels Basjes
Als Randnotiz: Wenn Sie dies mit einem tun möchten, müssen git mvSie das -kFlag verwenden, da git standardmäßig fehlschlägt und nicht nur eine Warnung ausspuckt. Also musst du tun git mv -k * ./new_dir.
Yuval A
11

Ein schneller und schmutziger Oneliner.

mv `ls -A | grep -v new_directory` ./new_directory

quelle
1
Funktioniert nicht: Ein einfaches ls zeigt keine Punktedateien an.
wzzrd
Sehr guter Punkt. Behebt das mit einem -a.
2
Anstatt also zu versuchen, new_directory für sich selbst zu definieren (ursprüngliche Frage), versuchen Sie jetzt, sich zu bewegen. und .. in neues_Verzeichnis.
Niels Basjes
2
Danke für die Rückmeldung Niels. Es wurde mit einem oberen a behoben, das das entfernt. und die .. aus der Verzeichnisliste.
8

Wenn Sie nur nach den Dateien suchen (dh nicht nach Verzeichnissen), dann

find . -type f -maxdepth 1 -exec mv {} ./new_directory/ \;

ist die tragbarste Lösung. Aus Geschwindigkeitsgründen sollten Sie find und xargs mit -print0 und -0 verschieben, aber nur, wenn Sie GNU find und xargs haben.

Cian
quelle
3
Wenn Sie einen relativ neuen GNU-Fund verwenden, können Sie auch \ + anstelle von \ verwenden. um die Anzahl der MVs zu verringern, die wir machen.
Wzzrd
Wenn Sie GNU find haben, können Sie auch xargs verwenden, die dasselbe tun und Sie können mehrere mvs gleichzeitig mit dem Flag -p ausführen.
Cian
coole Verwendung von find- obwohl ich auf jeden Fall auf Systemen war, die keine haben, leider :(
warren
"Ja wirklich?" find ist in SUS (afaik) spezifiziert, also sollte es alles haben. Das einzige Problem ist, ob es sich um GNU find (mit vielen tollen Optionen) oder um reguläre find handelt.
Cian
6

In den Zeiten, in denen ich dieses Problem hatte, habe ich eine der folgenden Aktionen ausgeführt:

$ mkdir ../new-directory
$ mv * ../new-directory/
$ mv ../new-directory .

oder

$ mkdir .new-directory
$ mv * .new-directory/
$ mv .new-directory new-directory

Die zweite Form nutzt den Platzhalter aus, der Dateinamen überspringt, die mit '.' Beginnen.

Kenster
quelle
Ich habe vergessen, dass die Platzhalter gepunktete Dateien übersprungen haben. Danke für die Erinnerung ! :)
aemonge
2

wie wäre es mit:

cd ..
mv old_dir new_directory
mkdir old_dir
mv new_directory old_dir

IOW, verschiebe den Inhalt nicht in ein neues Verzeichnis, sondern lege dieses Verzeichnis in ein neues.

Javier
quelle
1

In ähnlicher Weise wie bei @ Rembrane (allerdings kein Einzeiler ):

for FN in *
do
    if [ "<new_dir>" != $FN ] then
        mv $FN <new_dir>
done

Dies sollte zu 100% portabel sein - auch wenn findes auf Ihrem System leider nicht vorhanden ist.

Labyrinth
quelle
find wird in der Single-Unix-Spezifikation benötigt. Als solches sollte es niemals fehlen (nicht, dass man damit etwas nicht bauen könnte. Aber ich würde mir vorstellen, dass es einen entsetzlichen Aufwand erfordern würde, und es wird keinem Anbietersystem fehlen)
Cian,
Vielleicht ist es ein hyper-paranoider Sysadmin, der Findutils oder ähnliches sucht? Ich bin mir nicht sicher, aber ich weiß, dass ich auf Boxen gestoßen bin, die es nicht haben :(
warren
1

Meine Vorschläge: Wie von anderen angegeben

mv * ./new_directory

Wird funktionieren, finde IFF die Gesamtexpansion ist kurz genug.

Andernfalls können Sie dieses Programm ausprobieren, das sich auf eine viel größere Anzahl von Dateien skalieren lässt:

find . -type f -maxdepth 1 | xargs -s100000 echo | xargs -iXXX mv XXX new_directory

Erläuterung

  1. Alle Dateien auflisten.
  2. Gruppieren Sie alle Dateinamen zu Blöcken mit maximal 100000 Zeichen.
  3. Konstruieren Sie einen einzelnen MV-Befehl pro Block.
Niels Basjes
quelle
Bricht ab, wenn Ihre Dateinamen Leerzeichen enthalten
Cian
Du hast recht. Also denke ich, dass dies mit -print0 und -0 Flags ergänzt werden sollte, um dies zu beheben.
Niels Basjes
Ich habe es mit -print0und versucht -0und es bricht immer noch.
Cristian Ciupitu
find: warning: Sie haben die Option -maxdepth nach einem Nicht-Optionsargument -type angegeben, die Optionen sind jedoch nicht positionsgebunden (-maxdepth wirkt sich sowohl auf die zuvor als auch auf die danach angegebenen Tests aus). Bitte geben Sie Optionen vor anderen Argumenten an.
Cristian Ciupitu
1

Verwenden:

find -mindepth 1 -maxdepth 1 \! -name new_directory -print0 | \
    xargs -0 -P 100 -I'{}' mv '{}' new_directory

Von der xargsManpage:

-P max-procs

  Run up to max-procs processes at a time;
Cristian Ciupitu
quelle
-1

So vermeiden Sie die Fehlermeldung und halten Sie sie einfach:

mv *.* ./new_Folder

wird das Gleiche tun, aber die Fehlermeldung vermeiden (es sei denn, Sie haben Punkte in Ihren Ordnernamen, denke ich).

user157734
quelle