Obter arquivos com um nome contendo um valor de data menor ou igual a uma determinada data de entrada

7

Uma das minhas pastas contém arquivos no seguinte formato:

3_20150412104422154033.txt
3_2015041211022775012.txt
3_20150412160410171639.txt
3_20150412160815638933.txt
3_20150413161046573097.txt
3_20150413161818852312.txt
3_20150413163054600311.txt
3_20150413163514489159.txt
3_2015041321292659391.txt
3_20150414124528747462.txt
3_20150414125110440425.txt
3_20150414134437706174.txt
3_20150415085045179056.txt
3_20150415100637970281.txt
3_20150415101749513872.txt

Eu quero recuperar esses arquivos com um valor de data menor ou igual ao meu valor de data de entrada.

Por exemplo, se eu der "3_20150414" que é (3_YYYYMMDD), eu quero que a saída seja o nome do arquivo

3_20150412104422154033.txt
3_2015041211022775012.txt
3_20150412160410171639.txt
3_20150412160815638933.txt
3_20150413161046573097.txt
3_20150413161818852312.txt
3_20150413163054600311.txt
3_20150413163514489159.txt
3_2015041321292659391.txt
3_20150414124528747462.txt
3_20150414125110440425.txt
3_20150414134437706174.txt

Eu posso listar os arquivos emitindo um comando como este:

ls -l | grep '20150413\|20150414' |awk '{print $NF}'

Mas estou com dificuldades para encontrar uma correspondência <= .

    
por fortune 30.04.2015 / 08:42

3 respostas

6

Você pode usar awk e seu operador de comparação de string.

ls | awk '$0 < "3_20150415"'

Em uma variável:

max=3_20150414 export max
ls | LC_ALL=C awk '$0 <= ENVIRON["max"] "z"'

concatenar com "z" aqui garante que a comparação seja uma comparação de strings e permite a qualquer momento desse dia, já que no C locale, os dígitos ordenam antes de z .

    
por 30.04.2015 / 10:52
2

grep não tem um operador ≤ per se , mas há uma maneira desajeitada de fingir. Você quer todas as datas entre o ano 0 (ou o ano 1; qualquer que seja o primeiro ano) até 20150414. (Suponho que as datas do BC estão fora da mesa.) Divida esse intervalo em sub-intervalos que podem ser correspondidos por expressões regulares:

  • Ano 0 a 1999 - todos os anos começam com 0 ou 1, então grep para [01] .
    (Todas as expressões regulares serão consideradas ancoradas no início da linha, logo após o “3 _”.)
  • Ano de 2000 a 2009 - regex 200 .
  • Ano de 2010 até 2014 - regex 201[0-4] .
  • Ano de 2015, mês 1 até o mês 3 - 20150[1-3] .
  • Ano de 2015, mês 4, dia 1 a 9 - 2014040
  • Ano de 2015, mês 4, dia 10 a 14 - 2014041[0-4]

e depois junte tudo:

grep -E '3_([01]|200|201[0-4]|20150[1-3]|2015040|2015041[0-4])'

ls -l , é claro, fornece muitas informações sobre os arquivos (modo, proprietário, tempo de modificação, etc.) que você não precisa, então você usa awk '{print $NF}' para retirá-lo e deixar apenas o nome do arquivo. Isso é ineficiente e sujeito a erros (quebra se um nome de arquivo tiver um espaço ou uma tabulação nele). Analisar a saída de ls nunca é uma ótima ideia, mas você pode torná-lo um pouco mais seguro, tornando-o um pouco mais simples: apenas não receba as informações que você não quer ou precisa, e então você não precisa descartá-lo.

ls | grep -E '3_([01]|200|201[0-4]|20150[1-3]|2015040|2015041[0-4])'

deve ser bom o suficiente.

Mas construir essa expressão regular de seis partes é entediante e propenso a erros, e difícil (embora não impossível) para roteiro. Aqui está uma maneira mais clara:

ls | awk 'substr($1, 3, 8) <= 20150414'

Isto extrai os oito caracteres começando com a 3ª posição (ou seja, após o "3_") e compara-o com 20150414 como dois números de oito dígitos.

    
por 30.04.2015 / 09:47
1

Possível solução usando seu exemplo:

ls -l | grep '3_2015' | awk -v d='3_20150414' '{ s = substr($NF, 1, 10); if (length(s) == 10 && s <= d) print $NF; }'

Eu mudei um pouco o seu padrão grep e passei o valor pesquisado como argumento para awk , onde apenas comparamos strings para produzir as coisas desejadas.
Também há muitos artigos porque você não deve analisar ls então eu mudo um pouco com o find:

find . -type f -name '*3_2015*' -printf "%f\n" | awk -v d='3_20150414' '{ s = substr($NF, 1, 10); if (length(s) == 10 && s <= d) print $NF; }'
    
por 30.04.2015 / 09:48