Wie verschiebe ich alle Dateien vom aktuellen Verzeichnis in das übergeordnete Verzeichnis?


133

Wie verschiebe ich alle Dateien vom aktuellen Verzeichnis in das übergeordnete Verzeichnis unter Linux?

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


Ich habe nicht genug Repräsentanten, um Fragen zu wiederholen, aber kann ich [linux] [mv] [cwd] [files]etwas Ähnliches vorschlagen ?
Stephan202

Ich habe diese Frage gemäß der Anfrage von Stephan202 erneut beantwortet.
eleven81

Antworten:


202

Der gesuchte Befehl lautet

mv * .[^.]* ..

oder (siehe unten für weitere Informationen):

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

Erläuterung: Der mvBefehl verschiebt Dateien und Verzeichnisse. Das letzte Argument mvist das Ziel (in diesem Fall das Verzeichnis, das einen Schritt weiter oben in der Baumstruktur steht ..). Die Argumente davor sind die Quelldateien und -verzeichnisse. Das Sternchen ( *) ist ein Platzhalter, der allen Dateien entspricht, die nicht mit einem Punkt beginnen. Dateien, die mit einem Punkt beginnen (Punktdateien), werden "ausgeblendet". Sie werden anhand des Musters abgeglichen .[^.]*(siehe Bearbeitung unten).

Weitere Informationen finden Sie auf der von mir verlinkten Manpage mv.


Warum .[^.]*statt .*?

Wie Chris Johnsen richtig betont: Das Muster .*stimmt auch mit .und überein ... Da Sie diese nicht verschieben möchten (und können), ist es besser, ein Muster zu verwenden, das jedem Dateinamen entspricht, der mit einem Punkt beginnt, außer diesen beiden . Das Muster .[^.]*macht genau das: Es stimmt mit jedem Dateinamen (1) überein, beginnend mit einem Punkt (2), gefolgt von einem Zeichen, das kein Punkt (3) ist, gefolgt von null oder mehr beliebigen Zeichen.

Wie Paggas weist darauf hin , würden wir müssen auch das Muster hinzufügen , .??*um Dateien mit zwei Punkten beginnen zu lassen. Siehe seine Antwort für eine alternative Lösung mit find.

Arjans Antwort erwähnt shopt, 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 so zu benutzen:

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

Dies wird shoptin einer Subshell ausgeführt (daher kein zweiter Aufruf shopterforderlich) und verwendet, --damit Dateien, die mit einem Bindestrich beginnen, nicht als Argumente für interpretiert werden mv.


7
Die Verwendung von kann .*dazu führen, dass mv Warnungen / Fehler ausgibt , die darauf hinweisen , dass sich .und nicht bewegen können ... Sie könnten es mv * .[^.]* ..stattdessen versuchen .
Chris Johnsen

1
@alain: Gern geschehen und willkommen auf der Seite! (Wenn (und nur wenn) einer der Posts hier Ihre Frage ausreichend beantwortet hat, können Sie ihn als solchen markieren. Dadurch erhält das Poster 15 zusätzliche Reputationspunkte und Sie erhalten zusätzlich 2 Wiederholungen.)
Stephan202

Ich mag die Shopt-Lösung in einer Subshell :)
Paggas

2
Die Syntax *. * - einschließlich .. ist nur gefährlich, wenn sie mit chmod und chown und dem Flag "recurse" verwendet wird, dh chmod -R oder chown -R. Und in diesen Fällen nicht immer jemals geben chown * oder chmod . * -. Chown die Top-Verzeichnis im Pfad für Sie suchen und verwenden -h (folgen Sie nicht symbolische Links). Aber mv .. macht einfach nichts, also mach dir keine Sorgen.
Chris

1
Die richtigen drei Muster sind *, .[^.]*und ..?*. Die zweite vielleicht .[!.]*für ältere (POSIX) Shells. Lesen Sie auch

42

Kurze Antwort: verwenden

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

Lange Antwort:

Der Befehl

mv * .* ..

wird nicht funktionieren, da .*kann .und passen ... Aber der Befehl

mv * .[^.]* ..

wird auch nicht funktionieren, da .[^.]*passt zB nicht ..filename! Stattdessen mache ich

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

das passt zu allem außer .und ... *wird alles passen, der nicht mit einem Start ., .[^.]mit einem Punkt wird außer daß alle 2 - Zeichen Dateinamen übereinstimmen .., und .??*wird mit einem Punkt mit mindestens 3 Zeichen beginnen alle Dateinamen entsprechen.

Besser noch, Sie können verwenden

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

das vermeidet die hässlichen glob hacks in mv * .[^.] .??* ..!


1
Außerdem habe ich vergessen, die Wichtigkeit von - zu beachten, damit der Befehl bei Dateinamen, die mit einem Bindestrich beginnen, korrekt funktioniert. Ich habe die Antwort in meine Suche aufgenommen. Eine vollständigere Antwort unter Verwendung von Globs lautet "mv - *. [^.]. ?? * ..".
Paggas

+1: Ich bin zurückgekommen, um ..?*meinen Kommentar hinzuzufügen , und du hast dich bereits darum gekümmert.
Chris Johnsen

1
Was kann möglicherweise falsch daran sein, zu versuchen, mv ..? Es tut einfach nichts und kann nichts tun. Es gibt auch andere Befehle , wo es kann etwas (chmod und chown) tun , aber mv und rm einfach tun nichts zu. oder ..
Chris

1
Dies gibt mv: illegale Option - t
pal4life

1
Bono, die doppelten Gedankenstriche weisen Sie mvan, keine weiteren Befehlsoptionen mehr zu suchen. Die geschweiften Klammern ergeben einen Dateinamen. Das Pluszeichen besagt, dass anstelle der Ausführung von exec pro Ergebnis (dh pro Dateiname) so viele Ergebnisse wie möglich in einem einzigen exec abgelegt werden. Der Vollständigkeit -t..halber wird gesagt, dass das Ziel verschoben werden soll, um alle diese Dateien zu verschieben.
isuldor

14

Der Vollständigkeit halber kann man der Bash-Shell auch anweisen, versteckte Dateien einzuschließen, indem man verwendet shopt:

shopt -s dotglob
mv -- * ..
shopt -u dotglob

+1. Viel sauberer. Ich denke jedoch, dass eine leichte Verbesserung angebracht ist. Siehe das Update zu meiner Antwort.
Stephan202

8

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

cp -rf . ..

rm -rf *

Keine Notwendigkeit, sich mit komplexen Lösungen für das Aufsplittern und Verwenden von Suchbefehlen zu befassen.


Warnung Wenn Sie sich im selben Dateisystem befinden , haben Sie in den meisten Fällen die Dateien nicht wirklich kopiert, sondern nur die Verzeichniseinträge aktualisiert, ohne Inode oder Dateiinhalte zu verschieben. Siehe auch [1 ]. Mit einem cpund rmkopierst du wirklich alles.
Hastur

6
rsync -a --remove-source-files . ..

rsync ist ein äußerst leistungsfähiges Tool zum Kopieren von Dateien, das im Allgemeinen zur Durchführung effizienter inkrementeller Remote-Sicherungen und -Spiegelungen verwendet wird.

Mit dem obigen Befehl sagen wir, dass rsyncder Inhalt von .in kopiert werden soll..

Der Schalter -aermöglicht die Rekursion in .Unterverzeichnisse und aktiviert einige andere allgemeine Optionen.

Der Schalter --remove-source-filesweist rsync an, die Quelldateien nach einer erfolgreichen Kopie zu entfernen, dh rsync verhält sich ähnlich wie der mvBefehl.


1
Ein bisschen mehr Erklärung wäre schön.
ChrisF

Klar, ich hoffe es ist jetzt klarer.
Mrucci

Beachten Sie, dass --remove-source-files(synchronisierte) Verzeichnisse nicht entfernt werden.
Dennis

Schöne, akzeptierte Lösung gibt mir -bash: /bin/mv: Argument list too longFehler. Dieser arbeitet wie der Charme.
Userlond

2

Letztendlich wird der Versuch mv .scheitern, weil mv mv * ..die Verknüpfung zu dem Verzeichnis, in dem Sie sich gerade befinden, nicht aufheben kann. Sie können die Dateien in der CWD verschieben.


2
mv * .??* ../.

*Ruft alle Nicht-Punkt-Dateien ab. .??*bekommt alles. Mindestens drei Bytes lange Dateien, die für alle legitimen funktionieren. Alles, was Sie übrig haben, möchten Sie wahrscheinlich rmlieber als mvirgendwie.

Das ../.bietet keine direkten Vorteile gegenüber, ..aber wenn Sie ein Verzeichnis wechseln, ist es eine sehr gute Angewohnheit, sich darauf einzulassen, da es nach Belieben fehlschlägt, wenn etwas mit dem Pfad nicht stimmt. Wenn Sie beispielsweise glaubenmv xyz bletch , dass bletch es sich um ein Verzeichnis handelt, können Sie mit sicherer werden mv xyz bletch/..


2
Sie könnten hinzufügen .[^.], um Cover-Dateien wie zu erhalten .a.
Chris Johnsen

Es gibt keinen Unterschied zwischen ../ und ../. Ich würde mich also nicht darum kümmern, das zu tippen. nach dem Schrägstrich. Auch im Fall von mv und rm schadet es nicht, einzuschließen. und .. in der Liste, dh mit mv *. * / path / to / file / ist nichts unheimlich oder falsch, genauso wie mit rm. oder sogar -rf. macht nichts.
Chris

2

Dieser minimierte Befehl funktioniert auf den meisten modernen Shells:

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

Ansonsten wird eine portable Lösung genannt:

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

Eigenschaften:

  1. \ verhindert, dass Aliase sich unerwünscht verändern.

  2. - Verhindert, dass Dateinamen mit führenden Bindestrichen (-xyz) als Befehlszeilenargumente interpretiert werden.

  3. . [^.] stimmt mit allen zwei Zeichendateinamen überein, die mit. außer ..

  4. . ?? * stimmt mit allen anderen Dateinamen überein, die mindestens drei Zeichen lang sind.

Naive Implementierungen:

  1. Bei den folgenden Schritten werden versteckte UNIX-Dateinamen übersprungen, die mit "" beginnen. (.bashrc).

    mv * ..
    
  2. Die folgenden Übereinstimmungen .., die rekursiv versuchen, jedes Verzeichnis irgendwann ganz nach / in .. des aktuellen Arbeitsverzeichnisses ($ PWD oder pwd) zu verschieben. Benutze niemals.

    mv .* ..
    

2

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

mv -- * .[!.] .??* ..
  • -- Verhindert Probleme, wenn Sie einen Dateinamen haben, der mit beginnt -
  • * stimmt mit allen Dateinamen überein, die nicht mit einem beginnen .
  • Es gibt keine Dateinamen mit einem Buchstaben, die mit einem beginnen, .den Sie verschieben können / sollten
  • .[!.] stimmt mit allen Dateinamen mit zwei Zeichen überein, die mit einem beginnen .
  • .??* stimmt mit allen drei (oder längeren) Dateinamen überein, die mit a beginnen .

Mit ksh88 wird das Dateinamenmuster .[^.]tatsächlich mit den Dateinamen ..(die immer existieren) und .^(die wahrscheinlich nicht existieren) übereinstimmen , was eine entgegengesetzte Wirkung hat, als es gewünscht wird.


0

Finden und arbeiten auch. Diese Art von Struktur kann hilfreich sein, wenn Sie Dateien nach komplexeren Kriterien auswählen möchten, indem Sie find und egrep ändern.

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

mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..

0

Ich denke, die einfachste Lösung zum Verschieben aller Dateien in das übergeordnete Verzeichnis. wäre

mv "`ls`" ../

oder, Wenn versteckte Dateien / Verzeichnisse vorhanden sind

verwenden:

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

Nehmen wir an, Sie möchten den Inhalt eines Ordners in einen der internen Ordner verschieben (z. B.).

verwenden:

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

Hinweis:

"`ls -a`" 

Verschieben von Dateien mit Leerzeichen.

2>/dev/null

Ist für die Warnung / Fehler unterdrückt , weil ls -ader Druck würde .und ..Ordner , wie gut und man kann nicht verschoben oder kopiert werden . Für diese Ordner wird der 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 meiden, ls -awenn es keine versteckten Dateien gibt und nur benutzen ls.


Hast du versucht, was passiert, wenn du rennst mv $(ls -a)? Das würde auf das aktuelle Verzeichnis und das darunter liegende Verzeichnis tippen, da ls -aes ebenfalls ausgegeben wird ...
Sami Laine

Vielen Dank an @SamiLaine für den Vorschlag, den ich korrigiert habe. Hätte mv ls -a ../aber auch nach Bedarf geklappt, Ja es werden die oben genannten Fehler angezeigt aber ansonsten werden die benötigten Ordner / Dateien in das übergeordnete Verzeichnis verschoben.
Prabhat Kumar Singh

Dies funktioniert nicht für Dateien mit Leerzeichen.
Kenorb

@kenorb Sie müssen den lsBefehl in doppelte Anführungszeichen setzen, um Dateien mit Leerzeichen zu verschieben. Ich habe die erforderlichen Änderungen vorgenommen. Danke für den Hinweis.
Prabhat Kumar Singh
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.