Quelle est la façon la plus efficace de déplacer un grand nombre de fichiers qui résident dans un seul répertoire?

11

CentOS 5.x

Je m'excuse s'il s'agit d'une question répétée. J'ai vu beaucoup de questions similaires (concernant la suppression de fichiers) mais pas exactement le même scénario.

J'ai un répertoire contenant des centaines de milliers de fichiers (peut-être plus d'un million) et comme solution à court terme à un problème différent, je dois déplacer ces fichiers vers un autre emplacement.

Aux fins de la discussion, disons que ces fichiers résident à l'origine /home/foo/bulk/et que je souhaite les déplacer vers/home/foo2/bulk2/

Si j'essaye, mv /home/foo/bulk/* /home/foo2/bulk2/ j'obtiens une erreur "trop ​​d'arguments".

M. Google me dit qu'une alternative pour supprimer des fichiers en masse serait d'exécuter find. Quelque chose comme: find . -name "*.pdf" -maxdepth 1 -print0 | xargs -0 rm

Ce serait bien si je supprimais des trucs mais dans ce cas, je veux déplacer les fichiers ... Si je tape quelque chose comme find . -name "*" -maxdepth 1 -print0 | xargs -0 mv /home/foo2/bulk2/bash se plaint que le fichier n'est pas un répertoire.

Quelle est la meilleure commande à utiliser ici pour déplacer les fichiers en bloc d'un répertoire à un autre?

Mike B
la source

Réponses:

16

Profitant de mvl' -toption de GNU pour spécifier le répertoire cible, au lieu de s'appuyer sur le dernier argument:

find . -name "*" -maxdepth 1 -exec mv -t /home/foo2/bulk2 {} +

Si vous étiez sur un système sans l'option, vous pourriez utiliser un shell intermédiaire pour obtenir les arguments dans le bon ordre ( find … -exec … +ne prend pas en charge la mise d'arguments supplémentaires après la liste des fichiers).

find . -name "*" -maxdepth 1 -exec sh -c 'mv "$@" "$0"' /home/foo2/bulk2 {} +
Gilles 'SO- arrête d'être méchant'
la source
Vous pouvez utiliser find ... -exec sh -c 'blah "$ @" blah' sh {} + "(le" truc du shell ") pour traiter les problèmes liés à l'ordre des arguments. Il en existe plusieurs exemples dans les findutils ( info) documentation; recherchez "sh -c".
James Youngman
5

Envisagez mvle répertoire parent au lieu des fichiers:

mv /home/foo/bulk /home/foo2/bulk2 && mkdir /home/foo/bulk

(Mais cela peut causer des problèmes s'il /home/foo/bulkdoit exister à chaque instant.)

Scott
la source
1
J'ajouterais à cela, juste au cas où votre répertoire de destination existe, déplacez les fichiers du répertoire de destination vers votre répertoire source (le gros) et renommez le répertoire.
sbenitezb
Merci - super suggestion. Dans ce cas, le répertoire doit exister à chaque instant. Excellente idée cependant.
Mike B
Je dois admettre que je ne comprends pas ce que fait cette réponse. Pourquoi mkdir? Et qu'en est-il de ce répertoire «existant à chaque instant» ou non? Pourquoi cela accélérerait-il les choses?
Monica Heddneck
Je sais que ce commentaire date d'un an, mais le dernier avait cinq ans, alors j'ai pensé que je pouvais aussi bien répondre ... Vos deux premières questions sont corrélées. C'est mkdirparce que le dossier entier et tout ce qu'il contient seraient déplacés dans l'autre répertoire et n'existeraient plus dans l'ancien répertoire. Il garantit que l'ancien répertoire existe toujours. Cependant, cela ne serait pas suffisant s'il y avait un service en cours d'exécution qui dépendait du premier répertoire toujours existant, car il est déplacé puis recréé. Cela ne fait rien de plus rapide, juste plus simple en fournissant moins d'arguments.
Lucas Leblanc
0

Juste pour la variété, j'aime utiliser cpio pour certains cas comme celui-ci.

find tmp |cpio -v  -p --make-directories --sparse tmp2
Arthur Ulfeldt
la source
1
Si la source et la destination se trouvent sur le même système de fichiers, cette approche peut être très inefficace (copie inutile). De plus, il est toujours préférable d'utiliser -print0et d' -0options.
pabouk
0

Avec GNU mv:

find . -mindepth 1 -exec mv -t /tmp {} +

Sur des systèmes comme OS X qui n'ont pas mv -tmais ont -print0et xargs -0:

find . -mindepth 1 -print0|xargs -0 -I, mv , /tmp

Ou si les noms de fichiers ne contiennent pas d'espaces, de guillemets, de barres obliques inverses ou de nouvelles lignes (avec OS X xargs) ou de guillemets, de barres obliques inverses ou de nouvelles lignes (avec GNU xargs):

ls|xargs -I, mv , /tmp
Lri
la source
-3

Pour une durée spécifiée, essayez ce qui suit:

find . -name "*" -type f -mtime +7 -exec mv -t /folder/to/transfer/files {} +
jean
la source