J'essaie de mettre à jour l'horodatage à l'heure actuelle sur tous les fichiers XML de mon répertoire (de manière récursive). J'utilise Mac OSX 10.8.5.
Sur environ 300 000 fichiers, la echo
commande suivante prend 10 secondes :
for file in `find . -name "*.xml"`; do echo >> $file; done
Cependant, la touch
commande suivante prend 10 minutes ! :
for file in `find . -name "*.xml"`; do touch $file; done
Pourquoi l'écho est-il tellement plus rapide que le toucher ici?
echo >> $file
va ajouter une nouvelle ligne à$file
et donc le modifier. Je suppose que ce sera la même chose pour OS / X. Si vous ne le souhaitez pas, utilisezecho -n >> $file
.touch `find . -name "*.xml"`
encore plus rapide que les deux ci-dessus?>>$file
touch
autant de fois?find . -name '*.xml' -print0 | xargs -0 touch
invoquetouch
beaucoup moins de fois (éventuellement une seule fois). Fonctionne sous Linux, devrait fonctionner sous OS X.Réponses:
En bash,
touch
est un fichier binaire externe, maisecho
un shell intégré :Etant donné qu’il
touch
s’agit d’un fichier binaire externe et que vous appeleztouch
une fois par fichier, le shell doit créer 300 000 instances detouch
, ce qui prend beaucoup de temps.echo
, cependant, est un shell intégré, et l’exécution de shell n’a pas besoin de forking. Au lieu de cela, le shell actuel effectue toutes les opérations et aucun processus externe n'est créé; c'est la raison pour laquelle c'est tellement plus rapide.Voici deux profils des opérations du shell. Vous pouvez voir que l'on passe beaucoup de temps à cloner de nouveaux processus lors de l'utilisation
touch
. L'utilisation/bin/echo
du shell intégré devrait donner un résultat beaucoup plus comparable.Utiliser le toucher
Utilisation de l'écho
la source
Comme d' autres ont répondu, à l' aide
echo
sera plus rapide quetouch
commeecho
une commande qui est souvent (mais pas besoin d'être) à la coque intégrée. Son utilisation supprime la surcharge du noyau associée à l'exécution d'un nouveau processus pour chaque fichier que vous obteneztouch
.Toutefois, notez que le moyen le plus rapide d’atteindre cet effet est toujours d’utiliser
touch
, mais plutôt que d’exécuter le programme une fois pour chaque fichier, il est possible d’utiliser l’-exec
option avecfind
pour s’assurer qu’il n’est exécuté que quelques fois. Cette approche sera généralement plus rapide car elle évite la surcharge associée à une boucle shell:Utiliser
+
(par opposition à\;
) avecfind ... -exec
exécute la commande une seule fois, si possible, avec chaque fichier comme argument. Si la liste d'arguments est très longue (comme c'est le cas avec 300 000 fichiers), plusieurs analyses seront effectuées avec une liste d'arguments dont la longueur est proche de la limite (ARG_MAX
sur la plupart des systèmes).Un autre avantage de cette approche est qu’elle se comporte de manière robuste avec les noms de fichiers contenant tous les caractères d’espacement, ce qui n’est pas le cas de la boucle d’origine.
la source
+1
pour avoir souligné l'+
argument de recherche . Je pense que beaucoup de gens ne sont pas conscients de cela (je ne l'étais pas).find
n'ont pas l'+
argument. Vous pouvez obtenir un effet similaire en effectuant un piping toxargs
.+
pièce est requise par POSIX, elle devrait donc être portable.-print0
n'est pas.find
a l'option disponible mais la traite simplement comme un;
sous la surface.echo
est un shell intégré. D'autre part,touch
est un binaire externe.L'intégration de Shell est beaucoup plus rapide car il n'y a pas de temps système impliqué dans le chargement du programme, c'est-à-dire qu'il n'y a pas
fork
/exec
impliqué. En tant que tel, vous observeriez une différence de temps significative lorsque vous exécutez une commande interne par rapport à une commande externe un grand nombre de fois.C'est la raison pour laquelle des utilitaires similaires
time
sont disponibles en tant que commandes intégrées au shell.Vous pouvez obtenir la liste complète des commandes intégrées au shell en disant:
Comme mentionné ci-dessus, l'utilisation de l' utilitaire par opposition à l'utilisation intégrée entraîne une dégradation significative des performances. Voici les statistiques du temps pris pour créer environ 9 000 fichiers à l'aide de la commande intégrée
echo
et de l' utilitaireecho
:la source
echo
fichier binaire sur la plupart des systèmes (pour moi, c’est le cas/bin/echo
), vous pouvez donc réessayer les tests de minutage en l’utilisant à la place de la commande intégrée