web-dev-qa-db-fra.com

Comment fusionner un répertoire dans un autre en utilisant Bash?

Je recherche un script Shell qui fusionne les fichiers d'un répertoire dans un autre.

Échantillon:

html/
  a/
    b.html
  index.html

html_new/
  a/
    b2.html
    b.html

Usage:

./mergedirs.sh html html_new

Résultat:

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

html/a/b.html a été remplacé par html_new/a/b.html
html/a/b2.html a été copié à partir de html_new/a/b2.html
html/index.html n'a pas été touché

68
NVI

Vous voulez probablement juste cp -R $1/* $2/ - c'est une copie récursive.

(S'il peut y avoir des fichiers cachés (ceux dont les noms commencent par un point), vous devez préfixer cette commande avec shopt -s dotglob; pour être sûr qu'ils sont appariés.)

76
Luke Maurer
cp -RT source/ destination/

Tous les fichiers et répertoires dans source se retrouveront dans destination. Par exemple, source/file1 sera copié dans destination/file1.

Le -T le drapeau s'arrête source/file1 d'être copié dans destination/source/file1 au lieu.

77
Flimm

Jetez un œil à rsync

rsync --recursive html/ html_new/

Rsync a beaucoup de drapeaux à définir, alors regardez la page de manuel de rsync pour plus de détails

16
CarlG

Utilisez simplement rsync - c'est un excellent outil pour la copie de fichiers locaux et la fusion en plus de la copie à distance.

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

Notez que la barre oblique de fin du dossier source est nécessaire pour copier uniquement le contenu du dossier source vers la destination. Si vous ne le laissez pas, il copiera le dossier source_ et son contenu, ce qui n'est probablement pas ce que vous recherchez car vous voulez fusionner des dossiers.

6
Gavster

Ne serait pas cp -r travail?

cp -r html_new/* html

ou (puisque la première version ne copiera pas les fichiers ".something")

cd html_new; cp -r . ../html

Veuillez noter que -rlit à partir des canaux si l'un des fichiers du répertoire copié sont des canaux. Pour éviter cela, utilisez -R au lieu.

2
DVK
cd html
cp -r . /path/to/html_new
2
Brian Clapper

Même si cette question et sa réponse acceptée sont anciennes, j'ajoute ma réponse parce que celles qui utilisent actuellement cp ne gèrent pas certains cas Edge ou nécessitent un travail interactif. Souvent, les cas Edge/scriptabilité/portabilité/sources multiples n'ont pas d'importance, auquel cas la simplicité l'emporte, et il est préférable d'utiliser cp directement avec moins d'indicateurs (comme dans d'autres réponses) pour réduire la charge cognitive - mais pour ces autres fois (ou pour une fonction robustement réutilisable) cette invocation/fonction est utile, et incidemment n'est pas spécifique à bash (je réalise que cette question concernait bash cependant, donc c'est juste un bonus dans ce cas). Certains indicateurs peuvent être abrégés (par exemple avec -a), mais je les ai tous inclus explicitement sous forme longue (à l'exception de -R, voir ci-dessous) pour des raisons d'explication. Évidemment, supprimez simplement les drapeaux s'il y a une fonctionnalité que vous voulez spécifiquement ne faites pas que vous voulez (ou si vous êtes sur un système d'exploitation non-posix, ou votre version de cp ne traite pas cet indicateur - J'ai testé cela sur GNU coreutils 8.25's 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 ...]

Explication:

  • -R: a une sémantique subtilement différente de -r/--recursive sur certains systèmes (en particulier en ce qui concerne les fichiers spéciaux dans les répertoires source) comme expliqué dans cette réponse
  • --no-dereference: ne jamais suivre les liens symboliques dans SOURCE
  • --preserve=all: conserve les attributs spécifiés (par défaut: mode, propriété, horodatages), si possible des attributs supplémentaires: contexte, liens, xattr, tous
  • --force: si un fichier de destination existant ne peut pas être ouvert, supprimez-le et réessayez
  • --one-file-system: rester sur ce système de fichiers
  • --no-target-directory: traiter DEST comme un fichier normal (expliqué dans cette réponse , à savoir: 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.)
  • [entrée canalisée depuis yes]: même avec --force, dans ce mode récursif particulier cp demande toujours avant d'alimenter chaque fichier, donc nous obtenons la non-interactivité en redirigeant la sortie de yes vers lui
  • [sortie canalisée vers /dev/null]: c'est pour faire taire la chaîne de questions en désordre le long de cp: overwrite 'xx'?
  • [return-val & early exit]: cela garantit que la boucle se termine dès qu'il y a échec d'une copie et renvoie 1 en cas d'erreur

BTW:

  • Un nouveau drapeau génial que j'utilise également avec ceci sur mon système est --reflink=auto pour ce que l'on appelle des "copies légères" (copie sur écriture, avec les mêmes avantages de vitesse que la liaison physique, et les mêmes avantages de taille jusqu'à et en proportion inverse de la divergence future des fichiers). Cet indicateur est accepté dans les récents GNU cp, et fait plus qu'un no-op avec des systèmes de fichiers compatibles sur les noyaux Linux récents. YMWV-beaucoup sur d'autres systèmes.
2
Rowan Thorpe