Como encontrar arquivos entre duas datas usando “find”?

14

Eu tenho uma conta de e-mail que recebeu mais de 60 GB de e-mails, e atualmente estou tendo muitos problemas para usar um cliente de e-mail para arquivar e-mails do ano passado (2011).

Via terminal, estou tentando usar localizar para localizar os arquivos entre 2011 -01-01 e 2011-12-31, mas sem sucesso.

Como posso encontrar arquivos entre duas datas?

Se for relevante, o objetivo final será um lote que moverá cada arquivo encontrado, correspondente ao intervalo de datas, para uma pasta.

    
por Zuul 20.09.2012 / 20:31

3 respostas

12

Você pode usar este script:

#!/bin/bash
for i in $(find Your_Mail_Dir/ -newermt "2011-01-01" ! -newermt "2011-12-31"); do
  mv $i /moved_emails_dir/
done
    
por Octávio Filipe Gonçalves 20.09.2012 / 20:34
28

Bash encontra arquivos entre duas datas:

find . -type f -newermt 2010-10-07 ! -newermt 2014-10-08

Retorna uma lista de arquivos com registros de data e hora depois de 2010-10-07 e antes de 2014-10-08

Bash encontra arquivos de 15 minutos atrás até agora:

find . -type f -mmin -15

Retorna uma lista de arquivos com registros de data e hora depois de 15 minutos atrás, mas antes.

Bash encontra arquivos entre dois timestamps:

find . -type f -newermt "2014-10-08 10:17:00" ! -newermt "2014-10-08 10:53:00"

Retorna arquivos com registros de data e hora entre 2014-10-08 10:17:00 e 2014-10-08 10:53:00

    
por Eric Leschinski 08.10.2014 / 21:51
7

Movendo os arquivos e solicitando ao usuário quando houver nomes duplicados:

Como Subv3rsion e As respostas de Eric Leschinski mostram que o predicado -newermt seleciona os arquivos modificados mais recentemente do que a data (e a hora opcional) especificada como seu operando. Para encontrar arquivos

  • em qualquer lugar em srcdir (ou seja, incluindo seus subdiretórios, seus subdiretórios, etc.)
  • última modificação em (por exemplo) setembro de 2014
  • e mova-os para destdir

... você pode executar:

find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv -i {} destdir/ \;

Em uma expressão -exec , find passa o nome do arquivo encontrado no lugar de {} . ; significa para -exec que o comando a ser executado e seus argumentos foram todos fornecidos (no caso de expressões subseqüentes serem passadas para localizar após os argumentos específicos do predicado -exec - veja abaixo um exemplo disso) . ; deve ser escapado como \; , por isso não é interpretado especialmente pelo shell. (Sem \ , ; terminaria todo o comando find , funcionando da mesma forma que uma nova linha. Mesmo que esse comando find não tenha nada após essa expressão -exec , a falha em transmitir o argumento ; é ainda um erro de sintaxe.)

Se você quiser apenas listar os arquivos - o que é recomendável se você não tiver certeza de como os e-mails antigos estão armazenados ou quais outros arquivos podem estar presentes - omite -exec e tudo à direita. (Para e-mails, muitas vezes os e-mails de datas diferentes são armazenados no mesmo arquivo ; para alguém na situação descrita na pergunta aqui, recomendo investigar como eles são armazenados antes de mover qualquer arquivo.) Se você quiser para imprimir seus nomes e movê-los, adicione -print antes de -exec .

mv -i solicita a qualquer momento que um arquivo seja sobrescrito no destino, como acontece se:

  • existe um arquivo com o mesmo nome de um backup anterior, ou
  • um arquivo com o mesmo nome, mas de um subdiretório diferente srcdir , já foi movido durante a mesma operação find , ou
  • (menos provável) um arquivo com o mesmo nome foi criado em algum lugar em srcdir durante a mesma operação find , depois que o original foi movido, mas logo será encontrado uma vez find atravessa um subdiretório diferente.

Outras formas de invocar rm :

Você tem outras opções para lidar com arquivos com nomes duplicados.

  • Sem -i (ou seja, mv {} destdir/ ), mv normalmente não solicitaria aprovação, mas o faria se o arquivo de destino fosse somente leitura. ( mv pode até ser bem-sucedido ao sobrescrever um arquivo somente leitura algumas vezes, como, por exemplo, se o usuário que o executa possuir o arquivo.)
  • Se você não quiser nem mesmo esse grau de interatividade, e quiser que mv sempre (tente) sobrescreva arquivos com nomes idênticos, use mv -f .
  • Se, ao contrário, você quiser ignorar os arquivos de origem quando já houver um arquivo de destino com o mesmo nome, use mv -n .
  • mv aceita os sinalizadores -b e --backup para renomear automaticamente os arquivos com nome idêntico que já existem no destino. Por padrão, ~ é adicionado para produzir o nome do backup e, se um arquivo com o nome e um arquivo com o nome de backup já existir no destino, o arquivo de backup será sobrescrito. Esse padrão pode ser substituído pelas opções transmitidas ao chamar mv e pelas variáveis de ambiente. Consulte man mv para obter detalhes e o exemplo abaixo.

Movendo os arquivos e criando backups no caso de nomes duplicados:

Para mover todos os arquivos, fazer backup de arquivos com nomes duplicados usando um sufixo ~ e usar sufixos .~n~ numerados quando arquivos .~ já existirem (para evitar sobrescrever qualquer coisa), execute:

find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv --backup=existing {} destdir/ \;

Se você ignorou arquivos com nomes duplicados e quer saber quais:

Se você usa mv -n e deseja saber quais arquivos não foram movidos porque havia outro arquivo com o mesmo nome, provavelmente a melhor maneira é executar o comando find original novamente, sem -exec e tudo à direita dele. Isso imprimirá seus nomes.
Ele também imprimirá os nomes de todos os arquivos correspondentes criados desde que você executou o comando find .... -exec ... original, mas para esse aplicativo normalmente não haverá nenhum, pois você está procurando arquivos com tempos de modificação antigos. É possível fornecer a um arquivo um registro de data e hora de modificação mais antigo do que a sua idade real, com touch e outros mecanismos, mas isso não parece provável de ocorrer neste caso sem o seu conhecimento.

Sabendo imediatamente, pois os arquivos são ignorados devido a nomes duplicados:

mv -n não informa, nem retorna nenhum código de saída especial, quando se abstém de mover um arquivo.Portanto, se você deseja ser imediatamente informado sobre os arquivos ignorados enquanto find é executado, será necessário fazer uma etapa separada para isso. Uma maneira é:

find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv -n {} destdir/ \; \
    -exec [ -f {} ] \; -exec printf "\'%s' skipped (exists in \'%s')\n" {} destdir \; 

Algumas considerações técnicas menores: Isso avisa incorretamente se mv não copia um arquivo por um motivo diferente do existente no destino e sai reportando sucesso . Isso parece improvável, mas não tenho certeza se é impossível. Ele também sofre potencialmente uma condição de corrida : ele avisa quando não há nenhum erro real, se um novo arquivo do mesmo nome foram criados no mesmo local durante o curto espaço de tempo após o arquivo antigo ser movido e antes da verificação para ver se ele foi removido. (Considerando o aplicativo, duvido que algum problema realmente ocorra). Ele poderia ser reescrito para verificar o destino antes mover o arquivo em vez de depois: então a condição de corrida estaria relacionada aos arquivos de destino recém-criados de arquivos de origem. E, embora os erros e avisos relatados por find ou mv (ou [ , embora não haja nenhum), serão gravados em erro padrão , nosso aviso ...skipped (exists in... é gravado em padrão saída . Normalmente, ambos aparecem no seu terminal, mas isso pode ser importante se você estiver criando scripts.

Eu dividi o comando em duas linhas para facilitar a leitura. Pode ser executado dessa forma ou você pode remover o \ e a nova linha (ou seja, a quebra de linha).

Como funciona esse comando find ?

find predicados podem ser testes (como -type e -newermt ), usados para seus valores de retorno, ou ações (como -print e -exec ), que são frequentemente usados para seus efeitos colaterais.

Quando nenhum operador (como -a para e -o para ou ) é fornecido entre expressões, -a está implícito. find emprega avaliação de curto-circuito para e e ou . p q (ou seja, p -a q ) é verdadeiro somente se as expressões p e q forem verdadeiras, então q não precisa ser avaliado se p é falso. Embora muitas vezes não pensemos nisso nesses termos, é por isso que os testes devem ser verdadeiros para as ações ou testes subsequentes a serem avaliados. Por exemplo, suponha que find apareça em um diretório. Ele avalia -type f para false, então ele pode pular tudo depois.

Como testes, as ações são avaliadas como verdadeiras ou falsas também. Dessa forma, -exec informa se o comando executado foi encerrado relatando sucesso (verdadeiro) ou falha (falso). Temos essa cadeia de -exec expressões conectadas com implícito e :

-exec mv -n {} destdir/ \; -exec [ -f {} ] \; -exec printf "\'%s' skipped (exists in \'%s')\n" {} destdir \;

Isso tenta mover o arquivo e, se mv reportar falha, parar. Não queremos avisar sobre um arquivo ignorado corretamente se algum outro problema for o motivo pelo qual ele não foi movido.

Mas, se tiver êxito, ele executa o comando [ . Como find , [ suporta seu próprio tipo de expressões passadas como argumentos. [ -f {} ] verifica se o operando após -f (passado a ele por find no lugar de {} ) existe (e é um arquivo regular) e retorna true / success ou false / failure. sub> (Os status de saída de muitos comandos são melhor interpretados como significando sucesso ou falha, mas o status de [ é geralmente melhor interpretado como verdadeiro ou falso.)

Se [ retornou false, o arquivo desapareceu, por isso foi movido, portanto não há necessidade de fazer nada. Mas se [ retornou false, o arquivo ainda está lá. Então find avalia a próxima expressão -exec , que imprime a mensagem de aviso.

Leitura adicional

por Eliah Kagan 09.10.2014 / 03:46