Localizar arquivos (estritamente) mais antigos que outro arquivo

2

Quando implanto meu software, envio um arquivo compactado para o servidor de destino e extraio seu conteúdo. Além disso, ao mesmo tempo, também coloco um arquivo de metadados no diretório, detalhando o que foi implantado.

Se eu quiser encontrar algum arquivo que tenha sido alterado desde que eu implantei o software, posso simplesmente encontrar arquivos que tenham um novo horário de modificação do que o arquivo de metadados:

find . -newer deployment_metadata.txt

Isso é legal e direto.

Agora, também gostaria de encontrar arquivos mais antigos que o arquivo de metadados de implantação. Alguém poderia supor que você poderia usar o símbolo bang para negar a verificação "mais recente"

find . ! -newer deployment_metadata.txt

Mas 'não mais recente' não é equivalente a 'antigo', já que qualquer arquivo com o mesmo timestamp também é "não mais recente" - então o comando também inclui todos os arquivos que acabei de implantar!

Então, eu queria saber se eu estava faltando um truque quando se trata de encontrar arquivos (estritamente) antigos?

Minha solução atual é criar um novo arquivo (no diretório temporário) usando touch , que possui um tempo de modificação de um minuto antes do arquivo deployment_metadata.txt. Então eu posso usar os seguintes argumentos: ! -newer /var/tmp/metadtata_minus_1 .

Isso funciona, mas parece uma perda de tempo ter que criar e, em seguida, limpar o arquivo no diretório temporário - especialmente porque usuários diferentes podem estar usando meu script para verificar isso (não quero a propriedade do arquivo problemas, então, na verdade, vou até acrescentar ${USER} ao nome do arquivo.

    
por jwa 22.08.2013 / 12:16

2 respostas

1

Uma maneira é (ab) usar o horário da época. Aqui está um teste em que primeiro crio sete arquivos em sequência em um diretório vazio, onde os arquivos c# recebem "o mesmo" ctime em relação a find :

$ for i in a b "c1 c2 c3" d e; do touch $i; sleep 1; done
$ find -newer c2
.
./d
./e
$ find -not -newer c2
./c3
./c2
./a
./b
./c1
$ find -newerct @$(($(stat -c %Z c2)-1))
.
./c3
./d
./c2
./e
./c1
$ find -not -newerct @$(($(stat -c %Z c2)-1))
./a
./b

Isso deve representar todos os conjuntos possíveis de ctime relativos a c2 :

  1. ctime > %código%
  2. c2ctime
  3. c2ctime
  4. c2 < %código%

com correspondências um pouco difusas, pelo menos.

O terceiro comando obtém epoch ctime para o arquivo c2 , subtrai 1 via aritmética de shell e alimenta isso como referência a ctime (o c2 é necessário para que -newerct interprete é como um timestamp ) para localizar todos os arquivos com @ mais recente que este timestamp interpretado (consulte find in ctime ). O quarto comando nega esta correspondência e deve, na prática, fazer o que você quer se eu entendi a pergunta corretamente, se você colocar seu arquivo de referência como -newerXY no meu exemplo.

Observe que o deslocamento de "1 segundo" é um tanto arbitrário (que é o que eu quis dizer com "correspondência difusa"), e pode-se imaginar uma situação em que um erro possa ser construído. No entanto, os registros de data e hora dos arquivos não são "definidos" de qualquer maneira e não podem ser confiáveis, portanto, não posso imaginá-los para gerar problemas práticos ou de segurança em situações reais.

Na prática, você pode até querer aumentar o deslocamento de 1 segundo (vejo na sua pergunta que você usa 1 minuto agora), mas isso é um detalhe de implementação.

    
por 22.08.2013 / 13:11
2

Talvez canalize a saída find em um loop do comando test , que permitirá usar um teste "mais antigo que":

find ... | while read file;
do
  [ "$file" -ot deployment_metadata.txt ] && echo "$file"
done
    
por 22.08.2013 / 12:25