Extrai o número se as linhas do arquivo na ordem do nome do arquivo de data

2

Eu tenho uma pasta com arquivos csv cujos nomes de arquivo são datas, por exemplo: January-01-2018.csv , January-02-2018.csv , ..., April-30-2018.csv .

Usando o Bash, de preferência, quero extrair o número de linhas de cada arquivo csv, mas em ordem de data. ou seja, desejo extrair o número de linhas em January-01-2018.csv e, em seguida, January-02-2018.csv ... e, em seguida, April-30-2018.csv e assim por diante.

No momento, tudo que eu tenho é:

for filename in $(ls *.csv); do cat $filename | wc -l >> by_day.dat; done

Mas isso faz não cuidar da minha operação em "ordem crescente de data".

Alguma sugestão de como eu poderia conseguir isso? Eu gostaria de fazer isso usando o bash.

    
por drN 02.05.2018 / 14:26

1 resposta

3

Você pode fazer isso combinando algumas ferramentas comuns:

  • find para listar todos os arquivos .csv (não-ordenados) e executar um comando para cada
  • basename para extrair o nome do arquivo sem a extensão .csv do caminho
  • date para interpretar a especificação de data no nome do arquivo e convertê-la em um número facilmente classificável, como segundos desde 1970.
  • echo para imprimir o número calculado e o caminho real do arquivo em uma linha para cada arquivo
  • sort para ordenar os caminhos de arquivo de acordo com este número de data convertida
  • cut para extrair apenas os caminhos de arquivo novamente da lista combinada
  • xargs cat para construir um comando passando todos os nomes de arquivos para o comando cat para concatená-los.

A linha completa é assim, se todos os arquivos que desejamos processar estiverem localizados em uma pasta chamada datecsv :

$ find datecsv/ -name '*.csv' -exec bash -c 'echo "$(date -d "$(basename -s.csv "{}")" +%s) {}"' \; | sort -n | cut -d' ' -f2- | xargs cat
2018,1,1,aaa
2018,1,1,bbb
2018,1,2,ccc
2018,1,2,ddd
2018,4,30,eee
2018,4,30,fff

Meus arquivos de exemplo que produzem a saída acima são estes:

$ cat datecsv/April-30-2018.csv
2018,4,30,eee
2018,4,30,fff
$ cat datecsv/January-01-2018.csv
2018,1,1,aaa
2018,1,1,bbb
$ cat datecsv/January-02-2018.csv
2018,1,2,ccc
2018,1,2,ddd

Como você quer apenas o número da linha de cada arquivo, o comando para isso seria assim:

$ find datecsv/ -name '*.csv' -exec bash -c 'echo "$(date -d "$(basename -s.csv "{}")" +%s) {}"' \; | sort -n | cut -d' ' -f2- | xargs -n1 wc -l
2 datecsv/January-01-2018.csv
2 datecsv/January-02-2018.csv
2 datecsv/April-30-2018.csv

A única alteração é a última parte, em que usamos xargs -n1 wc -l em vez de xargs cat como acima.

Algumas notas: A abordagem acima baseia-se em seus nomes de arquivos sendo um formato que date pode analisar. Esse é o caso dos nomes de exemplo que você forneceu, mas pode ser quebrado se o formato for alterado. Também requer que o nome do arquivo termine com um .csv minúsculo. Não tenho certeza se alguns caracteres especiais em nomes de arquivos podem quebrar coisas (espaços provavelmente devem ser seguros, novas linhas certamente irão quebrar).

    
por Byte Commander 02.05.2018 / 14:53