Eu tenho um diretório que possui 10144911 arquivos nele. Até agora, tentei o seguinte:
for f in ls; do sed -i -e 's/blah/blee/g' $f; done
Bati minha concha, o ls
está em um tilda, mas não consigo descobrir como fazer um.
ls | xargs -0 sed -i -e 's/blah/blee/g'
Args em excesso para sed
find . -name "*.txt" -exec sed -i -e 's/blah/blee/g' {} \;
Não foi possível bifurcar mais, não há mais memória
Alguma outra idéia de como criar esse tipo de comando? Os arquivos não precisam se comunicar. ls | wc -l
parece funcionar (muito lento), por isso deve ser possível.
sed
para cada arquivo. Não tenho certeza se existe uma maneira de abrir, editar, salvar e fechar uma série de arquivossed
; se a velocidade for essencial, convém usar um programa diferente, talvez perl ou python.sed
é provavelmente mais rápido do que o lançamentopython
ouperl
também, exceto se você fizer tudo nesse intérprete.Respostas:
Faça uma tentativa:
Alimentará apenas um nome de arquivo para cada chamada de
sed
. Isso resolverá o problema "muitos argumentos para sed". A-P
opção deve permitir que vários processos sejam bifurcados ao mesmo tempo. Se 0 não funcionar (deve executar o maior número possível), tente outros números (10? 100? O número de núcleos que você tem?) Para limitar o número.fonte
find . -name \*.txt -print0
para evitar que o shell expandir o glob e tentando alloc espaço para 10 milhões de argumentos para encontrar .Testei esse método (e todos os outros) em 10 milhões de arquivos (vazios), chamados "hello 00000001" para "hello 10000000" (14 bytes por nome).
ATUALIZAÇÃO: Agora incluí uma execução de quatro núcleos no
'find |xargs'
método (ainda sem 'sed'; apenas echo> / dev / null) ..Aqui está um resumo de como as respostas fornecidas saíram quando executadas nos dados de teste mencionados acima. Esses resultados envolvem apenas as despesas gerais básicas; ou seja, 'sed' não foi chamado. O processo sed certamente será o mais demorado, mas pensei que seria interessante ver como os métodos simples eram comparados.
O
'find |xargs'
método de Dennis , usando um único núcleo, levou 4 horas e 21 minutos ** a mais do que obash array
método em umano sed
execução ... No entanto, a vantagem de vários núcleos oferecida por 'find' deve superar as diferenças de tempo mostradas quando o sed está sendo chamado. processando os arquivos ...fonte
Outra oportunidade para a descoberta completamente segura :
fonte
Isso é principalmente fora de tópico, mas você pode usar
O principal benefício aqui (acima
... xargs ... -I {} ... sed ...
) é a velocidade: você evita invocarsed
10 milhões de vezes. Seria mais rápido ainda se você pudesse evitar o uso do Python (já que o python é meio lento, relativamente), então o perl pode ser uma escolha melhor para esta tarefa. Não sei como fazer o equivalente convenientemente com o perl.A maneira como isso funciona é que
xargs
invocará o Python com o maior número de argumentos possível em uma única linha de comando e continuará fazendo isso até que fique sem argumentos (que estão sendo fornecidos porls -f *.txt
). O número de argumentos para cada invocação dependerá do tamanho dos nomes dos arquivos e de outras coisas. Afileinput.input
função gera linhas sucessivas dos arquivos nomeados nos argumentos de cada chamada, e ainplace
opção diz para "capturar" magicamente a saída e usá-la para substituir cada linha.Observe que o
replace
método de string do Python não usa regexps; se você precisar, precisaimport re
e usaprint re.sub(line, "blah", "blee")
. Eles são RegExps compatíveis com Perl, que são uma espécie de versões altamente fortificadas daquelas com as quais você se relacionased -r
.editar
Como akira menciona nos comentários, a versão original usando um glob (
ls -f *.txt
) no lugar dofind
comando não funcionaria porque os globs são processados pelo próprio shell (bash
). Isso significa que, antes que o comando seja executado, 10 milhões de nomes de arquivos serão substituídos na linha de comando. É praticamente garantido que exceda o tamanho máximo da lista de argumentos de um comando. Você pode usarxargs --show-limits
para obter informações específicas do sistema sobre isso.O tamanho máximo da lista de argumentos também é levado em consideração por
xargs
, o que limita o número de argumentos que ele passa para cada chamada de python de acordo com esse limite. Comoxargs
ainda será necessário chamar o python algumas vezes, a sugestão de akiraos.path.walk
para obter a lista de arquivos provavelmente economizará algum tempo.fonte
os.path.walk()
?.
e..
. Certamente, existem outras maneiras de fazer isso (ou sejafind
), mas estou tentando manter o mais próximo possível do que o OP entende. Este também é o motivo para não usaros.path.walk
.os.path.walk
facilmente.Experimentar:
fonte
ls -f
seria melhor; Deseja realmente esperarstat()
e classificar tantos arquivos?