web-dev-qa-db-fra.com

Comment écraser des fichiers cibles avec mv?

J'ai une tonne de fichiers et de répertoires dans un sous-répertoire que je souhaite déplacer vers le répertoire parent. Il existe déjà certains fichiers et répertoires dans le répertoire cible qui doivent être remplacés. Les fichiers qui ne sont présents que dans la cible ne doivent pas être modifiés. Puis-je forcer mvà le faire? Il (mv * ..) Se plaint

mv: cannot move `xyz' to `../xyz': Directory not empty

Qu'est-ce que je rate?

175
EricSchaefer

Vous devrez les copier vers la destination puis supprimer la source, à l'aide des commandes cp -r * .. suivi par rm -rf *.

Je ne pense pas que vous puissiez "fusionner" des répertoires en utilisant mv.

128
dogbane

rsync serait probablement une meilleure option ici. C'est aussi simple que rsync -a subdir/ ./.

Mon arbre de test au format filename: contents:

./file1:root
./file2:root
./dir/file3:dir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

Exécution de rsync:

$ rsync -a -v subdir/ ./
sending incremental file list
./
file1
dir/
dir/file3

Donne:

./file1:subdir
./file2:root
./dir/file3:subdir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

Et puis, pour émuler mv, vous voudrez probablement supprimer le répertoire source:

$ rm -r subdir/

Donnant:

./file1:subdir
./file2:parent
./dir/file3:subdir
./dir/file4:dir

Si cela ne va pas, pouvez-vous fournir un exemple similaire (par exemple en utilisant mon arbre de test près du haut de cette réponse) avec le résultat souhaité?

77
Mikel

rsync peut supprimer la source après des copies avec le --remove-source-files paramètre. Cela devrait être un moyen pratique de faire ce que vous souhaitez.

Du rsync man page:

        --remove-source-files   sender removes synchronized files (non-dir)
52
Mike Chen

Vous pouvez le faire avec cp et rm, mais sans copier l'énorme quantité de données que vous essayez (vraisemblablement) d'éviter de transférer. @mattdm y a fait allusion dans son commentaire , et ne réponse à une autre question a une discussion plus complète sur les différentes options.

cp -rlf source destination
rm -r source

Essentiellement, l'option -l Pour la commande cp crée des liens durs vers des fichiers plutôt que de copier leurs données dans de nouveaux fichiers.

24
palswim

Voici un script qui déplace les fichiers sous /path/to/source/root au chemin correspondant sous /path/to/destination/root.

  • Si un répertoire existe à la fois dans la source et dans la destination, le contenu est déplacé et fusionné de manière récursive.
  • Si un fichier ou un répertoire existe dans la source mais pas dans la destination, il est déplacé.
  • Tout fichier ou répertoire qui existe déjà dans la destination est laissé derrière. (En particulier, les répertoires fusionnés sont laissés dans la source. Ce n'est pas facile à corriger.)

Attention, code non testé.

export dest='/path/to/destination/root'
cd /path/to/source/root
find . -type d \( -exec sh -c '[ -d "$dest/$0" ]' {} \; -o \
                  -exec sh -c 'mv "$0" "$dest/$0"' {} \; -Prune \) \
    -o -exec sh -c '
        if ! [ -e "$dest/$0" ]; then
          mv -f "$0" "$dest/$0";
        fi
' {} \;

Ce fil existe depuis des années et se classe toujours n ° 1 sur Google, donc je voulais ajouter une autre méthode. Comment je fais habituellement cela: emballer le contenu de la sous-répertoire dans une archive tar, déplacer l'archive tar dans le répertoire parent, puis l'extraire avec le comportement par défaut --overwrite. Cela fait exactement ce que vous recherchez. Ensuite, vous pouvez supprimer votre sous-répertoire.

cd xyz
tar -cvzpf tmp.tar.gz *
mv tmp.tar.gz ../tmp.tar.gz
cd ..
tar -xvzpf tmp.tar.gz
rm -rf xyz
rm -f tmp.tar.gz
3
Simon Kraus

Si vous avez suffisamment de stockage, vous pouvez le faire de la manière suivante:

mv -bfv directory_1/* directory_2/ # all duplicate source files/directories 
                                   # will have ~ appended to them
find -name "*~" -delete            # will recursively find and delete all files 
                                   # with ~ on the end

Assurez-vous qu'il n'y a pas de fichiers importants avec un ~ à la fin, mais s'il y en a, vous pouvez ajouter --suffix=whateveryouwant au lieu de la valeur par défaut.

0
4D3H2