Script muito simples para remover as últimas 5 linhas de uma série de arquivos de texto

3

Por algum motivo, este script gera três arquivos para cada original, em vez de um.

Deve ter feito algum erro trivial - eu sou novo nisso!

Muito obrigado se alguém puder explicar por que isso acontece.

Script: -

for f in *.txt
do
   noOfRows=$(cat $f | wc -l)
   relevantRows=$(expr $noOfRows - 5)
   head -n $relevantRows $f | tee ${f%.txt}-Amended.txt
done

Resultado do comando ls: -

E12-5_F2_NEG-Amended-Amended-Amended.txt  E12-5_M3_POS-Amended-Amended-Amended.txt
E12-5_F2_NEG-Amended-Amended.txt          E12-5_M3_POS-Amended-Amended.txt
E12-5_F2_NEG-Amended.txt                  E12-5_M3_POS-Amended.txt
E12-5_F2_NEG.txt                          E12-5_M3_POS.txt
E12-5_F2_POS-Amended-Amended-Amended.txt  E12-5_M4_NEG-Amended-Amended-Amended.txt
E12-5_F2_POS-Amended-Amended.txt          E12-5_M4_NEG-Amended-Amended.txt
E12-5_F2_POS-Amended.txt                  E12-5_M4_NEG-Amended.txt
E12-5_F2_POS.txt                          E12-5_M4_NEG.txt
E12-5_F5_NEG-Amended-Amended-Amended.txt  E12-5_M4_POS-Amended-Amended-Amended.txt
E12-5_F5_NEG-Amended-Amended.txt          E12-5_M4_POS-Amended-Amended.txt
E12-5_F5_NEG-Amended.txt                  E12-5_M4_POS-Amended.txt
E12-5_F5_NEG.txt                          E12-5_M4_POS.txt
E12-5_F5_POS-Amended-Amended-Amended.txt  E12-5_M7_NEG-Amended-Amended-Amended.txt
E12-5_F5_POS-Amended-Amended.txt          E12-5_M7_NEG-Amended-Amended.txt
E12-5_F5_POS-Amended.txt                  E12-5_M7_NEG-Amended.txt
E12-5_F5_POS.txt                          E12-5_M7_NEG.txt
E12-5_M3_NEG-Amended-Amended-Amended.txt  E12-5_M7_POS-Amended-Amended-Amended.txt
E12-5_M3_NEG-Amended-Amended.txt          E12-5_M7_POS-Amended-Amended.txt
E12-5_M3_NEG-Amended.txt                  E12-5_M7_POS-Amended.txt
E12-5_M3_NEG.txt                          E12-5_M7_POS.txt

Muito obrigado, Adam

    
por user193170 27.01.2013 / 12:34

2 respostas

5

this script outputs three files for each original ... Much obliged if anyone could explain why this happens.

Como E12-5_F2_NEG-Amended.txt termina em .txt , ele será escolhido pelo seu script na próxima vez que você executá-lo.

Os resultados triplos indicam que você executou seu script três vezes ao depurá-lo.

Se a saída do script for $f.new em vez de ${f%.txt}-Amended.txt , você não terá esse problema.

Como alternativa, coloque rm *Amended.txt no início do programa. Se você tiver um número muito grande de arquivos em um diretório, isso pode ser lento em variantes Unix mais antigas.

Outra opção é enviar os arquivos para um subdiretório (então algo como "new/${f%.txt}.Amended.txt" )

    
por 27.01.2013 / 13:08
3

Você pode fazer o que seu script está tentando alcançar em uma única linha:

head --lines=-5 input.txt > output.txt

Em um loop for:

for f in *.txt; do head --lines=-5 "$f" > "${f%.txt}-Amended.txt"; done

Você pode usar -n -5 em vez de --lines=-5 para economizar na digitação, se quiser.

Como a RedGrittyBrick aponta, o motivo pelo qual você tem três arquivos por entrada provavelmente é porque você executou o script várias vezes e, como as saídas terminam com .txt, elas foram capturadas pelo glob * .txt dos scripts sucessivos.

Agora vou criticar seu script específico.

noOfRows=$(cat $f | wc -l)

Este é um verdadeiro uso inútil de gato ; em vez de cat $f | wc -l , use wc -l "$f" . Provavelmente não é tão importante neste roteiro específico, mas é bom não desenvolver maus hábitos. Falando sobre maus hábitos: Sempre cite variáveis , por exemplo %código%. Isso garantirá que o nome do arquivo seja tratado como um único argumento, mesmo que contenha espaço em branco.

relevantRows=$(expr $noOfRows - 5)

Não há nada realmente errado aqui, embora eu geralmente prefira usar algo como

relevantRows=$((noOfRows-5))

AFAIK não há diferença de desempenho entre os dois, mas acho o caminho mais visualmente agradável; e mais importante, a maneira que eu descrevi é definida no POSIX, e é, portanto, mais portátil . mais portável . Somente no bash (portanto, não use isso se você precisar portar o script para um shell diferente), a maneira melhor de fazer isso em um script seria usar let:

let noOfRows-=5

... que subtrairia 5 do número contido na variável $ noOfRows, significando que não há necessidade de criar a variável $ relevantRows.

head -n $relevantRows $f | tee ${f%.txt}-Amended.txt

Esta é a coisa correta a se fazer se você quiser que a saída seja exibida na linha de comando, bem como colocá-la em seu arquivo de saída. Caso contrário, use apenas "$f" para redirecionar o stdout para um arquivo.

    
por 27.01.2013 / 12:50