Estou tentando atualizar o registro de data e hora para o horário atual em todos os arquivos xml no meu diretório (recursivamente). Estou usando o Mac OSX 10.8.5.
Em cerca de 300.000 arquivos, o seguinte echo
comando leva 10 segundos :
for file in `find . -name "*.xml"`; do echo >> $file; done
No entanto, o touch
comando a seguir leva 10 minutos ! :
for file in `find . -name "*.xml"`; do touch $file; done
Por que o eco é muito mais rápido do que o toque aqui?
echo >> $file
arquivo anexará uma nova linha$file
e, portanto, a modificará. Presumo que será o mesmo para o OS / X. Se você não quiser isso, useecho -n >> $file
.touch `find . -name "*.xml"`
seria ainda mais rápido do que os dois itens acima?>>$file
touch
tantas vezes?find . -name '*.xml' -print0 | xargs -0 touch
invocatouch
muito menos vezes (possivelmente apenas uma vez). Funciona em Linux, deve trabalhar no OS X.Respostas:
No bash,
touch
é um binário externo, masecho
é um shell embutido :Como
touch
é um binário externo e você invocatouch
uma vez por arquivo, o shell deve criar 300.000 instânciastouch
, o que leva muito tempo.echo
, no entanto, é um shell embutido e a execução de shell embutidos não requer bifurcação. Em vez disso, o shell atual executa todas as operações e nenhum processo externo é criado; esta é a razão pela qual é muito mais rápido.Aqui estão dois perfis das operações do shell. Você pode ver que é gasto muito tempo clonando novos processos ao usá-lo
touch
. Usar em/bin/echo
vez do shell embutido deve mostrar um resultado muito mais comparável.Usando o toque
Usando eco
fonte
Como outros responderam, o uso
echo
será mais rápido do que otouch
queecho
é um comando que é comumente (embora não seja necessário) embutido no shell. Seu uso dispensa a sobrecarga do kernel associada à execução de um novo processo para cada arquivo que você obtémtouch
.No entanto, observe que a maneira mais rápida de obter esse efeito ainda está em uso
touch
, mas, em vez de executar o programa uma vez para cada arquivo, é possível usar a-exec
opção comfind
para garantir que seja executada apenas algumas vezes. Essa abordagem geralmente será mais rápida, pois evita a sobrecarga associada a um loop de shell:O uso de
+
(em oposição a\;
) comfind ... -exec
executa o comando apenas uma vez, se possível, com cada arquivo como argumento. Se a lista de argumentos for muito longa (como é o caso de 300.000 arquivos), várias execuções serão feitas com uma lista de argumentos com um comprimento próximo ao limite (ARG_MAX
na maioria dos sistemas).Outra vantagem dessa abordagem é que ela se comporta de maneira robusta com nomes de arquivos que contêm todos os caracteres de espaço em branco, o que não é o caso do loop original.
fonte
+1
por apontar o+
argumento find . Eu acho que muitas pessoas não estão cientes disso (eu não estava).find
têm o+
argumento. Você pode obter um efeito semelhante canalizando paraxargs
.+
peça é requerida pelo POSIX, portanto deve ser portátil.-print0
não é.find
tem a opção disponível, mas apenas a trata como uma;
parte inferior da superfície.echo
é um shell embutido. Por outro lado,touch
é um binário externo.Os componentes internos do shell são muito mais rápidos, pois não há sobrecarga envolvida no carregamento do programa, ou seja, não há
fork
/exec
envolvido. Como tal, você observaria uma diferença de tempo significativa ao executar um comando interno versus um comando externo várias vezes.Esta é a razão pela qual utilitários como
time
estão disponíveis como componentes internos do shell.Você pode obter a lista completa dos componentes internos do shell, dizendo:
Como mencionado acima, o uso do utilitário em oposição ao interno resulta em uma degradação significativa do desempenho. A seguir, estão as estatísticas do tempo necessário para criar ~ 9000 arquivos usando o builtin
echo
e o utilitárioecho
:fonte
echo
binário na maioria dos sistemas (para mim é/bin/echo
), então você pode repetir os testes de controle de tempo usando que em vez do built-in