Réponses:
mv
ne peut pas fusionner ou écraser des répertoires, il échouera avec le message "mv: impossible de déplacer" a "vers" b ": répertoire non vide" , même lorsque vous utilisez l' --force
option.
Vous pouvez contourner ce problème en utilisant d'autres outils (tels que rsync
, find
ou même cp
), mais vous devez examiner attentivement les implications:
rsync
peut fusionner le contenu d’un répertoire dans un autre (idéalement avec l’ option --remove-source-files
1 de ne supprimer en toute sécurité que les fichiers source transférés avec succès, et avec l’option habituelle autorisation / propriété / conservation de temps -a
si vous le souhaitez) rsync
l' --link-dest=DIR
option (créer des liens physiques au lieu de copier le contenu du fichier, si possible) et --remove-source-files
obtenir une sémantique très similaire à une image normale mv
. --link-dest
faut donner un chemin absolu au répertoire source (ou un chemin relatif de la destination à la source ). --link-dest
de manière non intentionnelle (ce qui peut causer ou non des complications), nécessite de connaître (ou de déterminer) le chemin absolu vers la source (en tant qu'argument --link-dest
), et laisse à nouveau une structure de répertoire vide à nettoyer en tant que pour 1 .find
pour recréer séquentiellement la structure de répertoires source sur la cible, puis déplacer individuellement les fichiers réels cp
peut créer des liens durs (simplement, pointeurs supplémentaires dans le même fichier existant), ce qui crée un résultat très similaire à une fusion mv
(et est très IO-efficace puisque seuls les pointeurs sont créés et aucune donnée réelle doit être copié) Laquelle de ces solutions de contournement (le cas échéant) est appropriée dépendra beaucoup de votre cas d'utilisation spécifique.
Comme toujours, réfléchissez avant d'exécuter l'une de ces commandes et effectuez des sauvegardes.
1: Notez que rsync --remove-source-files
cela ne supprimera aucun répertoire, vous devrez donc faire quelque chose comme find -depth -type d -empty -delete
par la suite pour vous débarrasser de l’arborescence du répertoire source vide.
mv
mise en œuvre utilisée par Debian - l'accent étant mis sur essayé , depuis la page de manuel ne mentionne pas ce comportement ...
--delete
seuls les fichiers du répertoire de destination qui n'existent pas dans le répertoire source ne sont supprimés .
-H
fonction ou vous pouvez lier des fichiers de la destination en utilisant --link-dest
. Voir la page de manuel avant de les utiliser, cependant.
rsync -av /source/ /destination/
(after checking)
rm -rf /source/
--remove-source-files
présente l’avantage de ne supprimer que les fichiers transférés avec succès. Vous pouvez find
donc supprimer des répertoires vides et conserver tout ce qui n’a pas été transféré sans avoir à vérifier la rsync
sortie.
Vous pouvez utiliser l' -l
option de la commande cp , qui crée des liens physiques de fichiers sur le même système de fichiers au lieu de copies avec données complètes. La commande suivante copie le dossier source/folder
dans un dossier parent ( destination
) qui contient déjà un répertoire avec le nom folder
.
cp -rl source/folder destination
rm -r source/folder
Vous pouvez également utiliser les options -P
( --no-dereference
- ne pas dé-référencer les liens symboliques) ou -a
( --archive
- conserver toutes les métadonnées, inclut également l' -P
option), en fonction de vos besoins.
cp
plutôt que rsync
depuis que chaque système a cp
et que tout le monde est familiarisé avec elle.
cp
avec le temps de fonctionnement de mv
.
-n
mv /fs1/file /fs2/
(sur tous les systèmes de fichiers) effectuera une copie puis une suppression.
mv
cela fonctionnera (à condition que le répertoire cible n'existe pas encore), même s'il n'est pas "efficacement" ou quoi que vous l'appeliez, cp -rl
échouera.
Je recommanderais ces quatre étapes:
cd ${SOURCE};
find . -type d -exec mkdir -p ${DEST}/\{} \;
find . -type f -exec mv \{} ${DEST}/\{} \;
find . -type d -empty -delete
ou mieux encore, voici un script qui implémente une sémantique semblable à mv
:
#!/bin/bash
DEST="${@:${#@}}"
ABS_DEST="$(cd "$(dirname "$DEST")"; pwd)/$(basename "$DEST")"
for SRC in ${@:1:$((${#@} -1))}; do (
cd "$SRC";
find . -type d -exec mkdir -p "${ABS_DEST}"/\{} \;
find . -type f -exec mv \{} "${ABS_DEST}"/\{} \;
find . -type d -empty -delete
) done
rsync -u
(ne mettre à jour que si plus récent), mv
(dans certaines versions au moins) peut également prendre l' -u
option. Toutefois, dans ce cas, vous voudrez peut-être supprimer les répertoires sources non vides, ainsi que ceux vides, pour couvrir les cas où les fichiers de l’arborescence des sources ne sont pas plus récents. @schuess: Il semble y avoir plusieurs arguments SOURCE, si vous en avez besoin.
Voici un moyen de fusionner les répertoires. Il est beaucoup plus rapide que rsync car il se contente de renommer les fichiers au lieu de les copier puis de les supprimer.
cd source; find -type f -print0 | xargs -0 -n 1 -I {} mv '{}' 'dest/{}'
dest
est déjà un répertoire portant le même nom que dans source
. Et les fichiers seront déplacés vers un dest
, qui est dans source
. La commande ne fait rien d'autre quemv source/* source/dest/.
Une façon d'y parvenir serait d'utiliser:
mv folder/* directory/folder/
rmdir folder
Tant qu'il n'y a pas deux fichiers portant le même nom en folder
et directory/folder
, vous obtiendrez le même résultat, à savoir la fusion.
rm folder
?
rm folder -fR
marche toujours pour moi
Pour les copies les plus pures, j'utilise la méthode de copie en lecture de blocs tar (-) B.
exemple, depuis le chemin source ('cd' là-bas si nécessaire):
tar cBf - <sourcefolder> | (cd /your/target/folder ; tar xBf -)
cela crée une copie exacte de l'arborescence source, avec le propriétaire et les autorisations intactes. Et si le dossier cible existe, les données seront fusionnées. Seuls les fichiers déjà existants seront écrasés.
Exemple:
$ cd /data1/home
$ tar cBf - jdoe | (cd /data2/home ; tar xBf -)
Lorsque l'action de copie réussit, vous pouvez supprimer la source ( rm -rf <source>
). Bien sûr, ce n’est pas un geste exact: les données seront copiées jusqu’à ce que vous supprimiez la source.
En option, vous pouvez être prolixe (afficher à l'écran le fichier en cours de copie), avec -v: tar cBvf -
c
: créerB
: lire le bloc complet (pour la lecture du tuyau)v
: verbeuxf
: fichier à écrirex
: extrait-
: stdout / stdinsourcefolder
peut aussi être *
(pour tout dans le dossier en cours)
f -
tar est généralement inutile - la valeur par défaut est de lire stdin / write sur stdout.
Voici un script qui a fonctionné pour moi. Je préfère mv à rsync, alors j'utilise les solutions de Jewel et Jonathan Mayer.
#!/bin/bash
# usage source1 .. sourceN dest
length=$(($#-1))
sources=${@:1:$length}
DEST=$(readlink -f ${!#})
for SRC in $sources; do
pushd $SRC;
find . -type d -exec mkdir -p ${DEST}/{} \;
find . -type f -exec mv {} ${DEST}/{} \;
find . -type d -empty -delete
popd
done
Ce n'est pas une bonne idée d'utiliser des commandes telles que cp ou rsync. Pour les gros fichiers, cela prendra beaucoup de temps. mv est beaucoup plus rapide puisqu'il ne fait que mettre à jour les inodes sans copier physiquement les fichiers. Une meilleure option consiste à utiliser le gestionnaire de fichiers de votre système d'exploitation. Pour Opensuse, il existe un gestionnaire de fichiers appelé Konquerer. Il peut déplacer des fichiers sans les copier. Il a "couper et coller" comme dans Windows. Il suffit de sélectionner tous les sous-répertoires du répertoire A. Cliquez avec le bouton droit de la souris et placez-vous dans le répertoire B qui peut contenir des sous-répertoires du même nom. Cela va les fusionner. Il existe également des options pour écraser ou renommer des fichiers portant le même nom.
mv
est utilisé.
Solution python
Comme je ne pouvais pas trouver une solution préexistante satisfaisante, j'ai décidé de créer un script Python rapide pour y parvenir.
En particulier, cette méthode est efficace car elle ne parcourt l'arborescence du fichier source qu'une fois ascendante.
Cela vous permettra également de modifier rapidement des options telles que la gestion de l'écrasement de fichiers à votre guise.
Usage:
move-merge-dirs src/ dest/
déplacera tout le contenu de src/*
dans dest/
et src/
disparaîtra.
move-merge-dirs
#!/usr/bin/env python3
import argparse
import os
def move_merge_dirs(source_root, dest_root):
for path, dirs, files in os.walk(source_root, topdown=False):
dest_dir = os.path.join(
dest_root,
os.path.relpath(path, source_root)
)
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
for filename in files:
os.rename(
os.path.join(path, filename),
os.path.join(dest_dir, filename)
)
for dirname in dirs:
os.rmdir(os.path.join(path, dirname))
os.rmdir(source_root)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Move merge src/* into dest. Overwrite existing files.'
)
parser.add_argument('src_dir')
parser.add_argument('dest_dir')
args = parser.parse_args()
move_merge_dirs(args.src_dir, args.dest_dir)
Cette commande permet de déplacer des fichiers et des dossiers vers une autre destination:
$ mv /source/path/folder /target/destination/
Rappelez - vous : la mv
commande ne fonctionnera pas si le dossier est bei̲n̲g me̲r̲ge̲d̲ (c’est-à-dire qu’un autre dossier portant le même nom existe déjà dans la destination) et que le dossier est dactylographié .
mv: impossible de déplacer "/ source / chemin / dossier" vers "/ cible / destination / dossier": répertoire non vide
Si le dossier de destination est vide, la commande ci-dessus fonctionnera correctement.
Donc, afin de fusionner les deux dossiers dans tous les cas,
soit le faire en 2 commandes:
$ cp -rf /source/path/folder /target/destination/
$ rm -rf /source/path/folder
Ou combinez les deux comme une commande unique:
$ cp -rf /source/path/folder /target/destination/ && rm -rf /source/path/folder
mv = move
cp = copy
rm = remove-r pour le répertoire (dossier)
-f force l'exécution
mv
. Cette réponse serait meilleure avec une vérité plus large. Linux, BSD et "réel" Unix, ou une référence de POSIX ou SUS.