J'ai des millions d'images sur mon serveur cloud ubuntu. Lorsque je déplace un dossier complet contenant 12 millions d'images à l'aide de la mv
commande, cela se produit presque instantanément. Cependant, lorsque je mv
ne fais que des images (pas le dossier), cela prend un certain temps. Existe-t-il un moyen de déplacer toutes les images aussi rapidement que les dossiers?
Voici ce qui se passe:
dossier src a 12 millions d'images et je le déplace vers le dossier dst en utilisant
$ mv src ../dst
Arrive immédiatement
Dans le dossier src, je fais cela pour déplacer:
find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ {} +
Cela prend du temps.
Existe-t-il un moyen d'accélérer le deuxième processus?
dst
est probablement dans une partition alors que../../dst
sur une autre.{}
argument où le ou les noms de fichiers seraient développés.find
.find ... -exec mv -t ../../dst/ {} \;
appelleraitmv
une fois par fichier;find ... -exec mv -t ../../dest {} +
serait beaucoup plus rapide, copiant autant de fichiers par appel que possible, mais toujours pas aussi rapidement que de déplacer le répertoire lui-même comme expliqué par dadexix86 .Réponses:
TL; DR : Non
Pour une plus petite quantité de fichiers, vous n'en auriez pas besoin
find
mais, même dans ce cas simplifié et plus petit, si vouscela prendra plus de temps que de déplacer le répertoire entier à la fois.
Pourquoi? Il s'agit de comprendre ce qui
mv
fait.En bref,
mv
déplace un nombre (qui identifie un répertoire ou un fichier) d'un inode (le répertoire qui le contient) vers un autre, et ces indices sont mis à jour dans le journal du système de fichiers ou dans le FAT (si le système de fichiers est mis en œuvre de cette manière).Si la source et la destination se trouvent sur le même système de fichiers, il n'y a pas de mouvement réel des données, cela modifie simplement la position, le point auquel elles sont attachées.
Ainsi, lorsque vous
mv
un répertoire, vous effectuez cette opération une fois .Mais lorsque vous déplacez 1 million de fichiers, vous effectuez cette opération 1 million de fois .
Pour vous donner un exemple pratique, vous avez un arbre avec de nombreuses branches. En particulier, il existe un nœud auquel 1 million de branches sont attachées.
Pour couper ces branches et les déplacer ailleurs, vous pouvez soit couper chacune d'elles, donc vous effectuez 1 million de coupes, soit vous coupez juste avant le nœud, faisant ainsi une seule coupe (c'est la différence entre déplacer les fichiers et le répertoire).
la source
mv
sur le même système de fichiers n'est qu'une réécriture de l'entrée de la table des matières.mv *.jpg
est susceptible d'échouer pour 12 millions de fichiers, c'est pourquoi il utilise find. La plupart des Unix, Linux inclus je crois (sauf si quelqu'un l'a changé au cours des 5 à 10 dernières années) ont une longueur maximale limitée de la ligne de commande. Je pense que c'était 64K pour Linux pendant longtemps. La même limite s'applique aux variables d'environnement, je suis presque sûr.Il sera toujours lent car, comme indiqué, le système de fichiers doit relier chaque nom de fichier à son nouvel emplacement.
Cependant, vous pouvez l'accélérer à partir de ce que vous avez actuellement.
Votre commande find exécute l'exéc une fois pour chaque fichier. Il lance donc la
mv
commande 12 millions de fois pour 12 millions de fichiers. Cela peut être amélioré de deux manières.Ajoutez un plus à la fin:
find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ +
consultez la page de manuel pour vous assurer qu'elle est prise en charge dans votre version de
find
. L'effet devrait être d'exécuter une série demv
commandes avec autant de noms de fichiers qu'il y en aura sur chaque ligne de commande.Utilisez
find
etxargs
ensemble.find -maxdepth 1 -name '*.jpg' -print0 | xargs -0 mv -t ../../dst/
Le
-print0
va utiliser NUL, alias zéro octet pour séparer les noms de fichiers. Ce plusxargs -0
corrige tous les problèmesxargs
qu'auraient autrement des espaces dans les noms de fichiers. Laxargs
commande lira la liste des noms de fichiers à partir de lafind
commande et exécutera lamv
commande sur autant de noms de fichiers qu'il conviendra.la source
Votre confusion vient de l'abstraction du système de fichiers qui vous fait croire qu'un dossier contient des fichiers et d'autres dossiers de manière arborescente. Ce n'est pas vrai en réalité: tous les fichiers et répertoires d'un système de fichiers sont situés au même niveau et identifiés avec des numéros d'une certaine sorte, selon l'implémentation. Les répertoires ne sont que des fichiers spéciaux qui contiennent des listes d'autres fichiers.
Lorsque vous "déplacez" des fichiers dans un système de fichiers, les fichiers réels ne vont nulle part. Les listes à l'intérieur des répertoires sont plutôt mises à jour pour refléter le changement.
mv src ../dst
déplace une seule entrée de liste d'un répertoire.
à l'autre../dst
, donc c'est rapide.find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/
doit déplacer des millions d'entrées, donc c'est plus lent. Elle peut potentiellement être accélérée si vous n'appelezmv
qu'une seule fois et pas une fois par fichier, et lamv
commande elle-même peut être optimisée pour déplacer plusieurs entrées de répertoire en une seule étape, mais il n'y a aucun moyen de la rendre aussi rapide que lorsque vous déplacez un seul répertoire .la source
Une réponse simplifiée
le déplacement d'un fichier se fait en 3 étapes:
ce processus est le même pour un fichier ou un dossier.
et évidemment faire cela pour 1 fichier est 100 plus rapide que le faire pour 100 fichiers.
man link
est le add ()man unlink
est le remove ()mv
utilise simplement ces deux commandes ci-dessus et ajoute une vérification entre les deux pour éviter la perte de données.la source