Comment déplacer en masse des fichiers vers un répertoire en toute sécurité?


10

Comment puis-je déplacer des fichiers dans un répertoire où il peut y avoir des centaines ou des milliers de fichiers dans le répertoire, et vous ne savez peut-être pas s'il y a des dupes dans ... Quelle méthode utiliseriez-vous?

La façon de gérer les dupes variera, parfois nous remplacerons, parfois nous devons être plus sûrs. Les E / S peuvent être importantes car ce sont des serveurs de production. Mais étant donné la quantité, une invite pour les fichiers non dupliqués n'est pas une option. La préservation des autorisations et des horodatages, etc., est importante. Nous ne savons généralement pas quelles sont les données.

Oh et son utilisation mvn'est pas requise rsync, les cpsolutions sont les bienvenues.

note: nous exécutons CentOS 5.5, alors faites-moi savoir si cela ne fonctionnera pas car il s'agit d'une fonctionnalité plus récente ...


Que voudriez-vous faire pour les dupes?

@Iain dépend de la situation? Je travaille chez un hébergeur ... cela dépend vraiment de mvet si nous nous soucions de la conservation dans le cas de ... et si nous avons déjà fait une sauvegarde. Cette question est assez ouverte. Je cherche juste de bonnes options, et peut-être un commentaire pour savoir si cela peut vous mordre et comment.
xenoterracide

Je suppose qu'il y a trop de fichiers pour le shell à gérer mv * ../ou mv -i * ../?
Michael Mrozek

@Michael Je suis sûr que cela varie ... dans certains cas, probablement pas. Dans certains cas, peut-être. J'essaie d'attraper autant d'options pour mon travail que possible.
xenoterracide

Réponses:


6

Je recommanderais d'utiliser rsync du parent:

rsync -avPr -b --suffix='-original' child/* .

qui sauvegardera tous les fichiers en double existants dans le parent vers le fichier -original.


Je pense que cela -aimplique-r
xenoterracide

@xenoterracide - Droite, vous 'r'
Tok

@Tok est-il possible de faire la copie en tant que liens physiques? afin de ne pas gaspiller IO. (comme -lpour cp)
xenoterracide

@xenoterracide - Vous pouvez utiliser les drapeaux -Hou --hard-linkspour rsync pour conserver les liens durs.
Tok

1
@xenoterracide - Vous pouvez utiliser l' --link-dest=DIRindicateur pour obtenir ce comportement comme: rsync -avP --link-dest=/path/to/src /path/to/src/* /path/to/dest/qui liera en dur dans dst / tous les fichiers inchangés entre src et src, dans ce cas tous les fichiers. Normalement, vous voyez cet indicateur utilisé lorsque vous souhaitez lier à nouveau des fichiers de sauvegarde sans copier leurs données, par exemple --link-dest=/most/recent/backup.
Tok

4
cp -bal . ..

Cela copiera tout ce qui se trouve dans le répertoire actuel dans le répertoire au-dessus, en conservant toutes les autorisations, en utilisant des liens physiques pour minimiser les E / S si possible, et sur les doublons, il crée un nom de fichier ~

après ça

rm -rf . ; cd .. ; rmdir <originaldir>;

se heurte probablement au grand nombre de problèmes de fichiers ... mais n'est pas intensif en IO comme rsync.
xenoterracide

2

Dans cet exemple, les fichiers seront déplacés de '/ parent / old-dir' vers '/ parent':

cd /parent

rsync -av --progress old-dir/ .

rm -rf old-dir

Selon les règles rsync, il remplacera les doublons par des fichiers plus récents old-dir.


1

Tu peux essayer

find . -maxdepth 1 -print0 | xargs -I '{}' -r0 mv '{}' ..

qui écrasera les fichiers de dupe dans ..

Vous pouvez utiliser mv -u '{}' pour ne pas écraser si la dupe dans .. est identique ou plus récente


pourquoi trouver des tuyaux à xargs? pourquoi ne pas utiliser +
xenoterracide

1
@xenoterracide - Habit et portabilité (c'est une extension GNU). En plus de cela, je viens de l'essayer et je ne sais pas comment passer le deuxième paramètre ..à la mv '{}' +commande car le + ajoute juste à la fin.

@Iain le + est dans POSIX, m'a-t-on dit précédemment que GNU avait trouvé tard pour l'obtenir.
xenoterracide

Vous avez raison, mais je n'arrive toujours pas à trouver un moyen d'utiliser le ..

2
@xenoterracide: Avec GNU coreutils: -exec mv -t .. -- {} +. Portably: -exec sh -c 'mv -- "$@"' _ {} +.
Gilles 'SO- arrête d'être méchant'

1

mv -i invite uniquement si la destination existe.

yes n | mv -i …déplace tous les fichiers qui n'existent pas dans le répertoire de destination. Sur FreeBSD et OSX, vous pouvez raccourcir cela en mv -n ….

Notez qu'aucun de ceux-ci ne fusionnera un argument de répertoire avec un répertoire existant du même nom dans le répertoire de destination.


Un problème distinct est de savoir comment agir sur tous les fichiers du répertoire en cours. Il y a deux problèmes: saisir tous les fichiers ( *omet les fichiers à points) et ne pas exécuter dans une ligne de commande. Sous Linux (ou plus généralement avec GNU find et GNU coreutils):

find . -mindepth 1 -maxdepth 1 -exec mv -i -t .. -- {} +

Avec GNU find mais pas GNU coreutils (ou les anciennes coreutils GNU):

find . -mindepth 1 -maxdepth 1 -exec sh -c 'mv -i -- "$@" "$0"' .. {} +

Portablement:

find . -name . -o -exec sh -c 'mv -i -- "$@" "$0"' .. {} -type d -prune

Comme d'habitude, zsh facilite les choses. Il n'a pas de limitation de longueur de ligne de commande en interne, donc si vous utilisez son mvintégré, vous n'avez pas à vous en soucier. Et vous pouvez lui dire de ne pas ignorer les fichiers dot avec le Dqualificatif glob. Limitation: cela ne fonctionne pas sur les systèmes de fichiers (à partir de zsh 4.3.10).

zmodload zsh/files
mv -i -- *(D) ..

à de nombreux arguments?
xenoterracide

0

J'ai dit sur notre ML

mv * ..

évidemment ce n'est pas très sûr ... cela écrasera les choses. Cela pourrait avoir des limites que je n'ai jamais rencontrées.


2
Si vous avez un grand nombre de fichiers, vous obtiendrez probablement une «liste d'arguments trop longue erreur».

2
Cela peut faire de mauvaises choses si vous avez un nom de fichier commençant par -. Il n'attrapera pas les fichiers dont le nom commence par ..
Gilles 'SO- arrête d'être méchant'

0

Ce qui suit est un modèle python que j'ai utilisé à bon escient dans le passé.

#!/usr/bin/env python
#
# Bart Kastermans, www.bartk.nl
#
# rename of collection of files in a directory
import os
import shutil

# only work on files whose name starts with a D
files = [filename for filename in os.listdir ("/Users/kasterma/Music/Audio Hijack/") if filename[0] =="D"]

for filename in files:
    shutil.move (filename, filename [:23] + ".mp3")
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.