Deixar os arquivos originais intactos e fazer o processamento nas cópias é uma boa ideia. Você deve ir mais além e não reutilizar os arquivos intermediários. Se você reutilizar os arquivos intermediários e o processo for interrompido, você não terá como saber em que ponto ele foi interrompido.
Você está aplicando a mesma transformação em dois arquivos. Não escreva o código duas vezes! Escreva o código uma vez, usando variáveis conforme necessário, e chame esse trecho de código uma vez para cada arquivo. Em um script de shell, a ferramenta para isso é escrever uma função (ou , se você precisar que esse código seja chamado de mais de um script, crie um script separado).
Todas as ferramentas de processamento de texto que você está usando podem ler da entrada padrão e gravar na saída padrão. Você pode combiná-los colocando um tubo entre a saída de uma ferramenta e a entrada da próxima ferramenta. Dessa forma, você não precisa de tantos arquivos intermediários - na verdade, você não precisa de nenhum arquivo intermediário nesse caso. Pipes são um recurso de design fundamental do Unix.
Uma outra dica de programação de shell: sempre colocam aspas duplas em torno de expansões variáveis , ou seja, $foo
.
#!/bin/bash
preprocess_csv () {
<"$1" \
tr -d '\r' |
awk '{ if(NR == 1) sub(/^\xef\xbb\xbf/,""); print }' >"${1%.csv}.clean"
}
preprocess_csv "$1"
preprocess_csv "$2"
do_stuff_with_preprocessed_file "${1%.csv}.clean" "${2%.csv}.clean" >global_output
Eu usei a expansão de parâmetro para construir ${1%.csv}
para transformar por exemplo foo.csv
into foo
, para que o arquivo de saída dessa transformação seja foo.clean
.
Esse script é mais simples do que você, mas ainda pode ser melhorado. Existem ferramentas melhores do que scripts de shell para descrever uma cadeia de comandos de processamento de arquivos: ferramentas de automação de construção como o clássico faça . Consulte Executar uma lista de comandos com pontos de verificação? para uma introdução a ser feita com um caso de uso semelhante. Veja como a transformação que você tem pode ser expressa com o make. Chame este arquivo Makefile
. Note que onde as linhas abaixo são recuadas com 8 espaços, você precisa substituir os 8 espaços por um caractere de tabulação, é uma peculiaridade de make.
default: global_output
%.clean: %.csv
<'$<' tr -d '\r' | awk '{ if(NR == 1) sub(/^\xef\xbb\xbf/,""); print }' >'$@'
global_output: input1.clean input2.clean
do_stuff_with_preprocessed_files input1.clean input2.clean >$@
$<
em um comando representa a dependência (o arquivo à direita do target: dependency
acima) e $@
representa o destino. Com o makefile acima, se você executar o comando make global_output
(ou apenas make
, graças à linha default:
no início), ele executará as transformações para produzir os arquivos .clean
(os arquivos .csv
já deve existir) e depois executará do_stuff_with_preprocessed_files
para produzir global_output
.
Este makefile é frágil porque deixa arquivos parcialmente processados se interrompidos no meio do caminho. Para corrigir isso, use arquivos temporários em cada regra, conforme explicado em Executar uma lista de comandos com checkpoint? .
default: global_output
%.clean: %.csv
<'$<' tr -d '\r' | awk '{ if(NR == 1) sub(/^\xef\xbb\xbf/,""); print }' >'[email protected]'
mv '[email protected]' '$@'
global_output: input1.clean input2.clean
do_stuff_with_preprocessed_files input1.clean input2.clean >'[email protected]'
mv '[email protected]' '$@'