bash script: uma maneira mais elegante de executar estas operações:

2

Eu tenho estes três arquivos:

arquivo.txt.7z = 5,4 GB
arquivo-1.txt.7z = 251M
arquivo-2.txt.7z = 7.7 M

E eles são os únicos arquivos em um diretório:

$ tree
.
├── file.txt.7z
├── file-1.txt.7z
└── file-2.txt.7z

Eu quero

  • descompacte os arquivos
  • combine-os em um arquivo
  • divide esse arquivo combinado em arquivos de 500.000 linhas
  • tem como resultado vários arquivos com extensão ".txt"

Agora eu estou conseguindo assim:

p7zip -d "*.txt.7z"
cat file-1.txt >> file.txt
rm file-1.txt
cat file-2.txt >> file.txt
rm file-2.txt
split -l 500000 file.txt
for f in *; do mv "$f" "$f.txt"; done

Como eu poderia conseguir isso de uma maneira mais elegante?

    
por assynti 18.10.2017 / 22:04

2 respostas

3

Solução

7za + split (único canal):

7za e "*.7z" -so 2> /dev/null | split -l500000 --additional-suffix=".txt" --numeric-suffixes=1 - "file"

- 7za opções:

  • e - extrair / descompactar arquivo (s)

  • -so - escreve o conteúdo em STDOUT

- split opções:

  • --additional-suffix=".txt" - acrescente o sufixo .txt a todos os nomes de arquivos resultantes

  • --numeric-suffixes=1 - use sufixos numéricos a partir de 1

  • - (hífen) - lê dados de STDIN (entrada padrão)

  • "file" - o prefixo comum para todos os nomes de arquivos resultantes

O comando acima resultará em arquivos com o seguinte formato de nomenclatura: file01.txt , file02.txt etc.

    
por 18.10.2017 / 23:01
1

Você pode usar pipes e a opção --filter de split após a descompactação:

p7zip -d *.txt.7z
cat file.txt file-1.txt file-2.txt | split -l 500000 --filter='> $FILE.txt'
rm file*

Aqui está a documentação para o --filter option :

‘--filter=COMMAND’
     With this option, rather than simply writing to each output file,
     write through a pipe to the specified shell COMMAND for each output
     file.  COMMAND should use the $FILE environment variable, which is
     set to a different output file name for each invocation of the
     command.  For example, imagine that you have a 1TiB compressed file
     that, if uncompressed, would be too large to reside on disk, yet
     you must split it into individually-compressed pieces of a more
     manageable size.  To do that, you might run this command:

          xz -dc BIG.xz | split -b200G --filter='xz > $FILE.xz' - big-

     Assuming a 10:1 compression ratio, that would create about fifty
     20GiB files with names ‘big-aa.xz’, ‘big-ab.xz’, ‘big-ac.xz’, etc.

Se você precisar manter um arquivo com toda a saída, você pode usar tee , que copia a entrada padrão para a saída padrão e para o arquivo fornecido como argumento.

cat file.txt file-1.txt file-2.txt |
    tee all.txt |
    split -l 50000 --filter='> $FILE.txt'
    
por 18.10.2017 / 22:14