Wie füge ich ein Verzeichnis mit Bash in ein anderes zusammen?


77

Ich suche nach einem Shell-Skript, das Dateien aus einem Verzeichnis in ein anderes zusammenführt.

Stichprobe:

html/
  a/
    b.html
  index.html

html_new/
  a/
    b2.html
    b.html

Verwendung:

./mergedirs.sh html html_new

Ergebnis:

html/
  a/
    b.html
    b2.html
  index.html

html/a/b.htmlwurde ersetzt durch html_new/a/b.html
html/a/b2.htmlwurde kopiert von html_new/a/b2.html
html/index.htmlwurde unberührt gehalten


1
Versucht cp -r html_new/* html? Sie können das html_newVerzeichnis anschließend entfernen .
ismail

Antworten:


86

Sie wollen wahrscheinlich nur cp -R $1/* $2/- das ist eine rekursive Kopie.

(Wenn möglicherweise versteckte Dateien vorhanden sind (deren Namen mit einem Punkt beginnen), sollten Sie diesem Befehl ein Präfix voranstellen, shopt -s dotglob;um sicherzustellen, dass sie übereinstimmen.)


93
cp -RT source/ destination/

Alle Dateien und Verzeichnisse in sourcelanden in destination. Zum Beispiel source/file1wird nach kopiertdestination/file1 .

Das -TFlag wird nicht source/file1mehr kopiert destination/source/file1. (Unter cpmacOS wird das -TFlag leider nicht unterstützt .)


funktioniert gut, es kopiert und führt / Ordner / Daten zu Ordner2 / Daten
nwgat

2
Ich bevorzuge diese Lösung, weil sie mit .dotfiles "wie sie ist" funktioniert.
fnkr

5
Unter Mac OS X / Darwin möchten Sie verwenden cp -r source/ destination- es ist schwierig, das / genau wie angegeben zu verwenden.
Ron Wertlen

Stolz darauf, derjenige zu sein, der diese Antwort positiv bewertet und sie jetzt der aktuell akzeptierten entspricht 😄.
Hadrien TOMA

Bitte beachten Sie, dass alle Dateien im Ziel überschrieben werden, die denselben Namen wie die Quelle haben
brianegge

17

Schauen Sie sich rsync an

rsync --recursive html/ html_new/

Rsync hat eine Menge Flags zu setzen. Weitere Informationen finden Sie in der Manpage zu rsync


6

Verwenden Sie einfach rsync - es ist ein großartiges Tool zum Kopieren und Zusammenführen lokaler Dateien sowie zum Remote-Kopieren.

rsync -av /path/to/source_folder/ /path/to/destination_folder/

Beachten Sie, dass der abschließende Schrägstrich im Quellordner erforderlich ist, um nur den Inhalt des Quellordners in das Ziel zu kopieren. Wenn Sie es weglassen, werden der Quellordner und sein Inhalt kopiert. Dies ist wahrscheinlich nicht das, wonach Sie suchen, da Sie Ordner zusammenführen möchten.


Es gibt einen kleinen Tippfehler, einen zusätzlichen Bindestrich, also sollte es seinrsync -av /path/to/source_folder/ /path/to/destination_folder/
vim

4

Obwohl diese Frage und ihre akzeptierte Antwort uralt sind, füge ich meine Antwort hinzu, da die derzeit vorhandenen Fragen cpentweder einige Randfälle nicht behandeln oder interaktiv arbeiten müssen. Oft spielen Edge-Cases / Skriptfähigkeit / Portabilität / mehrere Quellen keine Rolle. In diesem Fall gewinnt die Einfachheit, und es ist besser, cpdirekt mit weniger Flags (wie in anderen Antworten) zu verwenden, um die kognitive Belastung zu verringern - aber für diese anderen Zeiten (oder für eine robust wiederverwendbare Funktion) Dieser Aufruf / diese Funktion ist nützlich und übrigens nicht bash-spezifisch (mir ist klar, dass es sich bei dieser Frage um Bash handelt, also ist das in diesem Fall nur ein Bonus). Einige Flags können abgekürzt werden (zB mit-a ), aber ich habe alle explizit in Langform aufgenommen (außer-Rsiehe unten) zur Erläuterung. Entfernen Sie einfach alle Flags, wenn es eine Funktion gibt, die Sie speziell nicht möchten (oder wenn Sie ein Nicht-Posix-Betriebssystem verwenden oder Ihre Version cpdieses Flags nicht verarbeitet - ich habe dies auf GNU Coreutils 8.25 getestet cp):

mergedirs() {
    _retval=0
    _dest="$1"
    shift
    yes | \
        for _src do
            cp -R --no-dereference --preserve=all --force --one-file-system \
                  --no-target-directory "${_src}/" "$_dest" || { _retval=1; break; }
        done 2>/dev/null
    return $_retval
}

mergedirs destination source-1 [source-2 source-3 ...]

Erläuterung:

  • -R: hat eine subtil andere Semantik als -r/ --recursiveauf einigen Systemen (insbesondere in Bezug auf spezielle Dateien in Quellverzeichnissen), wie in dieser Antwort erläutert
  • --no-dereference: Folgen Sie niemals symbolischen Links in SOURCE
  • --preserve=all: Behalten Sie die angegebenen Attribute bei (Standard: Modus, Besitz, Zeitstempel), wenn möglich zusätzliche Attribute: Kontext, Links, xattr, alle
  • --force: Wenn eine vorhandene Zieldatei nicht geöffnet werden kann, entfernen Sie sie und versuchen Sie es erneut
  • --one-file-system: Bleiben Sie in diesem Dateisystem
  • --no-target-directory: Treat DEST als normale Datei (erklärt in in dieser Antwort , nämlich: If you do a recursive copy and the source is a directory, then cp -T copies the content of the source into the destination, rather than copying the source itself.)
  • [piped input from yes]: Auch wenn --forcein diesem speziellen rekursiven Modus cpnoch gefragt wird, bevor jede Datei überlastet wird, erreichen wir eine Nicht-Interaktivität, indem wir die Ausgabe von dort yesan sie weiterleiten
  • [Ausgabe an /dev/null] weitergeleitet: Dies dient dazu, die unordentliche Reihe von Fragen nach dem Vorbild von zum Schweigen zu bringencp: overwrite 'xx'?
  • [return-val & Early Exit]: Dies stellt sicher, dass die Schleife beendet wird, sobald eine Kopie fehlgeschlagen ist, und kehrt zurück, 1wenn ein Fehler aufgetreten ist

Übrigens:

  • Ein funky neues Flag, das ich auch auf meinem System verwende, ist das --reflink=autoErstellen sogenannter "Light Copies" (Copy-on-Write) mit den gleichen Geschwindigkeitsvorteilen wie beim Hardlink und den gleichen Größenvorteilen bis und in umgekehrtem Verhältnis um wie viel die Dateien in der Zukunft divergieren). Dieses Flag wird in der letzten GNU akzeptiert cpund ist mehr als ein No-Op mit kompatiblen Dateisystemen auf neueren Linux-Kerneln. YMWV-viel auf anderen Systemen.


2

Würde nicht cp -rfunktionieren?

cp -r html_new/* html

oder (da die erste Version keine ".something" -Dateien kopiert)

cd html_new; cp -r . ../html

Bitte beachten Sie, dass -r aus Pipes gelesen wird, wenn es sich bei einer der Dateien im kopierten Verzeichnis um Pipes handelt. Um dies zu vermeiden, verwenden Sie -Rstattdessen.


Berücksichtigen Sie beim "Zusammenführen" mehrerer Verzeichnisse usw. auch die Option -n(kein Clobber) oder -f(erzwingen), vorhandene Dateien beizubehalten oder zu überschreiben.
Tomasz Gandor
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.