Maneira mais rápida de concatenar arquivos


25

Tenho 10k + arquivos, totalizando mais de 20GB, que preciso concatenar em um arquivo.

Existe uma maneira mais rápida do que

cat input_file* >> out

?

A maneira preferida seria um comando bash, o Python também é aceitável, se não consideravelmente mais lento.


Atualizei minha resposta, findnão classifica os arquivos da mesma forma que um shell glob.
Graeme

5
Toda e qualquer solução (sã) terá uma velocidade equivalente aqui, já que o tempo será de 99% de E / S do sistema.
Goldilocks


3
Considere gravar o arquivo concatenado em um disco diferente daquele em que você está lendo.
Luis

11
Será mais rápido se outestiver localizado em outro disco.

Respostas:


30

Não, gato é certamente a melhor maneira de fazer isso. Por que usar python quando já existe um programa escrito em C para esse fim? No entanto, você pode querer considerar o uso xargs, caso o comprimento da linha de comando exceda ARG_MAXe você precise de mais de um cat. Usando as ferramentas GNU, isso é equivalente ao que você já possui:

find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z |
  xargs -0 cat -- >>out

11
Você pode garantir, nesse caso, que seus arquivos sejam lidos na ordem?
Kiwy

11
Sim, porque a saída de findé canalizada sort. Sem isso, os arquivos seriam listados em uma ordem arbitrária (definida pelo sistema de arquivos, que poderia ser a ordem de criação de arquivos).
Scal

@scai I missread muito, com espécie é bastante óbvio
kiwy

11
@ Kiwy, o único caso que vejo é que, se o local não estiver definido corretamente no ambiente, a classificação poderá se comportar de maneira diferente de uma bashglob. Caso contrário, não vejo casos em que xargsou catnão se comportariam conforme o esperado.
Graeme

3
@MarcvanLeeuwen, xargsligará o catquanto for necessário para evitar um erro E2BIG do execve (2).
Stéphane Chazelas

21

Alocar o espaço para o arquivo de saída primeiro pode melhorar a velocidade geral, pois o sistema não precisará atualizar a alocação para cada gravação.

Por exemplo, se no Linux:

size=$({ find . -maxdepth 1 -type f -name 'input_file*' -printf '%s+'; echo 0;} | bc)
fallocate -l "$size" out &&
  find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z | xargs -r0 cat 1<> out

Outro benefício é que, se não houver espaço livre suficiente, a cópia não será tentada.

Se ativado btrfs, você poderá copy --reflink=alwayso primeiro arquivo (que não implica cópia de dados e, portanto, seria quase instantâneo) e anexar o restante. Se houver 10000 arquivos, isso provavelmente não fará muita diferença, a menos que o primeiro arquivo seja muito grande.

Existe uma API para generalizar isso para copiar novamente todos os arquivos (o BTRFS_IOC_CLONE_RANGE ioctl), mas não consegui encontrar nenhum utilitário que exponha essa API; portanto, você deve fazê-lo em C ( pythonou em outros idiomas, desde que possam chamar ioctls arbitrários ) .

Se os arquivos de origem forem esparsos ou tiverem grandes seqüências de caracteres NUL, você poderá criar um arquivo de saída esparso (economizando tempo e espaço em disco) com (nos sistemas GNU):

find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z | xargs -r0 cat | cp --sparse=always /dev/stdin out

11
@XTian, ​​não, não deveria ser nem >nem >>, mas 1<>como eu disse para escrever no arquivo.
Stéphane Chazelas

5
@grebneke, <>é o operador padrão de redirecionamento de leitura e gravação Bourne / POSIX. Consulte o manual do shell ou a especificação POSIX para obter detalhes. O padrão fdé 0para o <>operador ( <>é abreviado para 0<>, como <é abreviado 0<e >abreviado 1>), portanto, você precisa 1redirecionar explicitamente o stdout. Aqui, não é muito o que precisamos ler + escrever ( O_RDWR), mas não queremos O_TRUNC(como em >) o que desalocaria o que acabamos de alocar.
Stéphane Chazelas

11
@grebneke, unix.stackexchange.com/search?q=user%3A22565+%22%3C%3E%22 fornecerá alguns. O ksh93 tem operadores de busca BTW, e você pode avançar com ddou via leitura.
Stéphane Chazelas

11
@StephaneChazelas - muito obrigado, sua ajuda e conhecimento são profundamente apreciados!
grebneke

11
Não estou convencido de que haverá muitos casos em fallocateque negaremos a sobrecarga do extra find, mesmo que seja mais rápido na segunda vez. btrfscertamente abre algumas possibilidades interessantes.
Graeme
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.