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é
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.)
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.
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
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.
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 -r
lit à partir des canaux si l'un des fichiers du répertoire copié sont des canaux. Pour éviter cela, utilisez -R
au lieu.
cd html
cp -r . /path/to/html_new
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.
)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/dev/null
]: c'est pour faire taire la chaîne de questions en désordre le long de cp: overwrite 'xx'?
1
en cas d'erreurBTW:
--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.