Como mesclar pedaços de arquivos de texto em um diretório para um ou mais arquivos?

2

Eu tenho um requisito para mesclar pedaços de arquivos de texto em um diretório para um ou mais arquivos e, em seguida, zipar o arquivo mesclado.

Por exemplo: se eu tiver meio milhão de arquivos de texto em um diretório, digamos A. Quero mesclar conjuntos de 50.000 arquivos em 1, ou seja, terei 10 arquivos mesclados, cada um com o conteúdo de 50.000 arquivos. Por fim, quero compactar cada arquivo mesclado, ou seja, haverá 10 arquivos zip no final desse processo.

Eu tentei fazer isso no shell script. Não consigo encontrar uma solução.

Alguém pode me informar a maneira mais eficiente de conseguir isso usando um script de shell?

    
por nka 22.08.2012 / 16:41

2 respostas

2

Como posso ver, você tem apenas um diretório com um grande conjunto de arquivos, portanto, é necessário dividir a lista de arquivos em pequenos conjuntos, depois concatená-los, depois zipar e, se necessário, excluir arquivos pequenos.

Eu posso sugerir apenas da seguinte maneira:

cd /to/dir/with/many/files/
mkdir ../tmp
find . | split -l 50000 ../tmp/x
for i in ../tmp/x* ; do 
    while read filename ; do
        cat "$filename" >> "${i}.text" ;
        # rm "$filename" # uncomment it only if you need to delete small files
    done <"$i"
    zip "${i}.zip"  "${i}.text"
    # rm "${i}.text" # uncomment it only if you need to delete result file
done
    
por 22.08.2012 / 16:58
1

Aqui estão duas soluções, uma em que n arquivos são adicionados a um único arquivo e um em que todos os arquivos são primeiro concatenados e depois compactados.

Os passos comuns para ambas as abordagens são:

# Generate a list of files to be zipped
find . -type f > filelist

# Loop to process n files stepwise
n=50000
fileno=1

for i in $(seq 1 $n $(wc -l < filelist)); do
  # compression code goes here, see below
done

Arquivos zip individualmente

# automatic name generation
zipfile=$(printf "%04d" $((fileno++)))

# extract lines $i to $i+$n-1 from filelist 
sed -n "$i,$((i+n-1))p" filelist | zip $zipfile -@

Concatenar e zipar

Se você quisesse fazer isso com gzip (e outros compressores), seria bem simples:

zipfile=$(printf "%04d" $((fileno++)))
sed -n "$i,$((i+n-1))p" filelist | xargs cat | gzip > $zipfile.gz

Como zip não suporta este modo (pelo menos não o que eu tenho), você precisa de uma abordagem diferente. zip suporta pipes nomeados ( -FI ) onde o arquivo dentro do arquivo recebe o nome do pipe nomeado, portanto, fazer algo parecido com isso dentro do loop deve funcionar:

zipfile=$(printf "%04d" $((fileno++)))
mkfifo $zipfile
zip -FI $zipfile $zipfile &
sed -n "$i,$((i+n-1))p" filelist | xargs cat > $zipfile
rm $zipfile
    
por 22.08.2012 / 16:51