2009-10-28 18:54:06 +0000 2009-10-28 18:54:06 +0000
134
134

Wie verschiebe ich alle Dateien aus dem aktuellen Verzeichnis in das obere Verzeichnis?

Wie verschiebt man unter Linux alle Dateien aus dem aktuellen Verzeichnis in das obere Verzeichnis?

Ich habe etwas wie mv *.* versucht, aber es funktioniert nicht.

Antworten (11)

204
204
204
2009-10-28 19:01:58 +0000

Der gesuchte Befehl ist

mv * .[^.]* ..

oder (siehe unten für weitere Informationen):

(shopt -s dotglob; mv -- * ..)

Erklärung: Der Befehl mv verschiebt Dateien und Verzeichnisse. Das letzte Argument von mv ist das Ziel (in diesem Fall das Verzeichnis eine Stufe “höher” im Baum, ..). Die Argumente davor sind die Quelldateien und -verzeichnisse. Das Sternchen (*) ist ein Platzhalter, der auf alle Dateien passt, die nicht mit einem Punkt beginnen. Dateien, die mit einem Punkt beginnen (Punktdateien), sind “versteckt”. Sie werden mit dem Muster .[^.]* abgeglichen (siehe Bearbeitung unten).

Siehe die Manpage, die ich verlinkt habe, für weitere Informationen zu mv.


Warum .[^.]* anstelle von .* ?

Wie Chris Johnsen richtig feststellt: das Muster .* passt auch auf . und ... Da Sie diese nicht verschieben wollen (und können), ist es besser, ein Muster zu verwenden, das auf jeden Dateinamen passt, der mit einem Punkt beginnt außer diesen beiden. Das Muster .[^.]* tut genau das: Es passt auf jeden Dateinamen (1), der mit einem Punkt beginnt (2), gefolgt von einem Zeichen, das kein Punkt ist (3), gefolgt von null oder mehr beliebigen Zeichen.

Wie Paggas anmerkt , müssten wir auch das Muster .??* hinzufügen, um Dateien zu finden, die mit zwei Punkten beginnen. Siehe seine Antwort für eine alternative Lösung mit find .

In Arjans Antwort wird shopt erwähnt, um all diese Probleme mit Punktdateien zu vermeiden. Aber dann gibt es immer noch das Problem mit Dateien, die mit einem Bindestrich beginnen. Und es erfordert drei Befehle. Trotzdem gefällt mir die Idee. Ich schlage vor, es wie folgt zu verwenden:

(shopt -s dotglob; mv -- * ..)

Dies führt shopt in einer Subshell aus (also kein zweiter Aufruf von shopt erforderlich) und verwendet --, damit Dateien, die mit einem Bindestrich beginnen, nicht als Argumente für mv interpretiert werden.

45
45
45
2009-10-28 20:19:07 +0000

Kurze Antwort: Verwenden Sie

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

Lange Antwort:

Der Befehl

mv * .* ..

wird nicht funktionieren, da .* mit . und .. übereinstimmen kann. Aber der Befehl

mv * .[^.]* ..

wird auch nicht funktionieren, da .[^.]* z. B. nicht mit ..filename übereinstimmt! Stattdessen mache ich

mv * .[^.] .??* ..

, was mit allem übereinstimmt, außer mit . und ... * passt auf alles, was nicht mit einem . beginnt, .[^.] passt auf alle Dateinamen mit 2 Zeichen, die mit einem Punkt beginnen, außer .., und .??* passt auf alle Dateinamen, die mit einem Punkt beginnen und mindestens 3 Zeichen haben.

Besser noch, Sie können

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

verwenden, was die hässlichen Glob-Hacks in mv * .[^.] .??* .. vermeidet!

14
14
14
2009-10-28 20:52:27 +0000

Nur der Vollständigkeit halber kann man der Bash-Shell auch sagen, dass sie versteckte Dateien einbinden soll, indem man shopt verwendet:

shopt -s dotglob
mv -- * ..
shopt -u dotglob
8
8
8
2011-08-02 20:46:48 +0000

Dem mv fehlt bei der Verwendung von * die Funktionalität, versteckte Dateien zu verschieben - warum also nicht stattdessen copy verwenden?

cp -rf . ..

rm -rf *

Keine Notwendigkeit, sich mit komplexen Lösungen von Dotglobbing und der Verwendung von Find-Befehlen zu beschäftigen.

7
7
7
2013-01-20 11:47:53 +0000
rsync -a --remove-source-files . ..

rsync ist ein extrem leistungsfähiges Dateikopierwerkzeug, das im Allgemeinen für die Durchführung effizienter inkrementeller Remote-Backups und Spiegelungen verwendet wird.

Mit dem obigen Befehl weisen wir rsync an, den Inhalt von . in .. zu kopieren

Der Schalter -a aktiviert die Rekursion in .-Unterverzeichnisse und aktiviert einige andere gängige Optionen.

Der Schalter --remove-source-files weist rsync an, die Quelldateien nach einem erfolgreichen Kopiervorgang zu entfernen, d. h. er bewirkt, dass sich rsync ähnlich wie der Befehl mv verhält.

2
2
2
2011-08-12 08:12:49 +0000

Dieser minimierte Befehl funktioniert auf den meisten modernen Shells:

\mv -- {,.{[^.],??}}* ..

Ansonsten handelt es sich um eine portable Lösung:

\mv -- * .[^.] .??* ..

Features:

  1. \ verhindert, dass Aliase mv ungewollt verändern.

  2. – verhindert, dass Dateinamen, die führende Bindestriche (-xyz) enthalten, als Befehlszeilenargumente interpretiert werden.

  3. .[^.] findet alle zweistelligen Dateinamen, die mit . beginnen, außer ..

  4. .??* findet alle anderen Dateinamen, die drei Zeichen oder länger sind.

Naive Implementierungen:

  1. überspringt versteckte UNIX-Dateinamen, also solche, die mit . (.bashrc) beginnen.

  2. Das Folgende passt zu .., das rekursiv versucht, jedes Verzeichnis eventuell bis zurück nach / in .. des aktuellen Arbeitsverzeichnisses ($PWD oder pwd) zu verschieben. Niemals verwenden.

2
2
2
2009-10-28 18:59:46 +0000

Letztendlich wird der Versuch mv . fehlschlagen, weil mv nicht in der Lage ist, die Verknüpfung mit dem Verzeichnis, in dem Sie sich gerade befinden, aufzuheben. Sie könnten mv * .. verwenden, um die Dateien im cwd zu verschieben.

2
2
2
2013-10-22 22:24:11 +0000

Es ist korrekter, das Muster * .[!.] .??* als * .[^.] .??* zu verwenden, da ersteres auch mit älteren Shells wie ksh88 funktioniert:

mv -- * .[!.] .??* ..
  • -- verhindert Probleme, wenn Sie einen Dateinamen haben, der mit - beginnt
  • * passt auf alle Dateinamen, die nicht mit einem . beginnen
  • es gibt keine einstelligen Dateinamen, die mit einem . beginnen, die Sie verschieben können/sollen
  • .[!.] passt auf alle zweistelligen Dateinamen, die mit einem . beginnen
  • .??* passt auf alle dreistelligen Dateinamen (oder länger), die mit einem . beginnen

Mit ksh88, passt das Dateinamensmuster .[^.] tatsächlich auf die Dateinamen .. (der immer existiert) und .^ (der wahrscheinlich nicht existiert), was das Gegenteil von dem bewirkt, was gewünscht ist.

2
2
2
2009-10-28 19:47:28 +0000
mv * .??* ../.

* bekommt alle nicht-gepunkteten Dateien. .??* holt alle . Dateien, die mindestens drei Bytes lang sind, was für alle legalen Dateien funktioniert. Alles, was übrig bleibt, wollen Sie wahrscheinlich sowieso lieber rm als mv.

Das ../. bietet keine direkten Vorteile gegenüber .., aber beim Verschieben in ein Verzeichnis ist es eine sehr gute Angewohnheit, denn es wird, wie Sie wollen, fehlschlagen, wenn etwas mit dem Pfad nicht stimmt. Zum Beispiel kann mv xyz bletch, wo man denkt, dass bletch ein Verzeichnis ist, mit mv xyz bletch/. sicherer gemacht werden.

0
0
0
2014-05-12 23:08:11 +0000

Find und grep funktionieren auch. Diese Art von Struktur könnte hilfreich sein, wenn Sie Dateien nach komplizierteren Kriterien auswählen möchten, indem Sie find und egrep modifizieren.

find -maxdepth 1 | egrep '^./.' # Returns all files

mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..
0
0
0
2014-08-06 16:37:16 +0000

Ich denke, die einfachste Lösung für das Verschieben aller Dateien in ihr übergeordnetes Verzeichnis wäre

mv "`ls`" ../

oder, wenn es versteckte Dateien/Verzeichnisse gibt,

verwenden:

mv "`ls -a`" ../ 2>/dev/null

Auch, sagen wir mal, Sie wollen den Inhalt eines Ordners in einen seiner internen Ordner verschieben tony(say)

use:

mv "`ls -a`" /tony 2>/dev/null

Hinweis:

"`ls -a`"

Um die Dateien zu verschieben, die Leerzeichen enthalten.

2>/dev/null

dient zur Unterdrückung der Warnung/Fehlermeldung, da ls -a auch die Ordner . und .. ausgeben würde und Sie diese nicht verschieben oder kopieren können. Für diese Ordner wird also ein Fehler angezeigt (wenn wir nicht 2>/dev/null verwenden), dass sie nicht verschoben werden können, und der Rest wird ganz bequem verschoben.

Am besten vermeiden Sie ls -a, wenn es keine versteckten Dateien gibt und verwenden nur ls.