como faço para verificar no bash se um arquivo foi criado há mais de x tempo?


106

Quero verificar no Linux Bash se um arquivo foi criado há mais de x tempo.

digamos que o arquivo se chama text.txt e o tempo é de 2 horas.

 if [ what? ]
 then
     echo "old enough"
 fi

Respostas:


138

Apenas para hora de modificação

if test `find "text.txt" -mmin +120`
then
    echo old enough
fi

Você pode usar -cminpara alterar ou -aminpara tempo de acesso. Como outros apontaram, não acho que você possa controlar o tempo de criação.


3
você pode descartar 'teste' e os acúmulos. Isso é análogo a 'if (test == true)' vs 'if (test)'
armas em

2
Você está certo; Suponho que estava pensando que findretornou diferente de zero quando nenhuma correspondência foi encontrada.
armas de

4
Você pode abandonar os backticks e fazer if test $ (find text.txt -mmin +120)
tommy.carstensen

1
@BroSlow parece melhor: não "mais de um" possível. Claro, text.txtpresume-se que não seja um diretório.
kmkaplan

2
Eu prefiro esta sintaxe:[ "$(find path/to/file -mmin +120)" ] && echo "it is old"
Alfe

42

Sempre gostei de usar date -r /the/file +%spara descobrir sua idade.

Você também pode fazer touch --date '2015-10-10 9:55' /tmp/filepara obter um tempo extremamente refinado em uma data / hora arbitrária.


Eu estava procurando a mesma coisa hoje. Melhor!
Umair A.

Obrigado. Eu caí nessa questão porque pesquisei "como imprimir a idade do arquivo bash." Então isso é exatamente o que eu estava procurando!
Noah Sussman

5
Obrigado! com a única ressalva de que o acima é um carimbo de data / hora (não a idade), mas pode ser usado para calcular a idade assim let AGE=$(($(date +%s)-$(date -r /path/to/file +%s))) [com a suposição de que criou e nunca modificou, ou "idade em relação ao mod"]
nh

function file-age { FILE_CREATED_TIME=`date -r "$1" +%s`; TIME_NOW=`date +%s`; echo "$[ ${TIME_NOW} - ${FILE_CREATED_TIME} ]"; }
turiyag

1
@turiyag Nota obrigatória que $[ ]é, se não obsoleto , pelo menos antigo e menos portátil , e deve-se usar em seu $(( ))lugar; e backquotes são mais frágeis do que $( ); e também hífens em nomes de função podem não ser totalmente portáveis. A essência disso é boa!
michaelb958 - GoFundMonica

23

Usando o statpara descobrir a data da última modificação do arquivo, datepara descobrir a hora atual e um uso liberal de bashismos, pode-se fazer o teste que você deseja com base na hora da última modificação do arquivo 1 .

if [ "$(( $(date +"%s") - $(stat -c "%Y" $somefile) ))" -gt "7200" ]; then
   echo "$somefile is older then 2 hours"
fi

Embora o código seja um pouco menos legível do findque a abordagem, acho que é uma abordagem melhor do que executar findpara examinar um arquivo que você já "encontrou". Além disso, a manipulação de datas é divertida ;-)


  1. Como Phil observou corretamente, o tempo de criação não é registrado, mas use ao %Zinvés do %Yabaixo para obter o "tempo de mudança" que pode ser o que você deseja.

[Atualizar]

Para usuários de mac, use em stat -f "%m" $somefilevez da sintaxe específica do Linux acima


Em que shell são integrados date e stat? Meu bash (GNU, 3.2.48) não os tem.
Ian Clelland,

OPA, desculpe. statnão está embutido - muito ruim da minha parte, vou consertar.
Guss,

1
A solução certa da @Guss é instalar coretutils com brew. :-)
Erik Johansson

1
@ErikJohansson Eu prefiro não exigir a instalação de software adicional quando usar o existente funciona bem - este não é o Windows, você sabe ;-)
Guss

1
Para as pessoas que desejam usar isso, mas modificá-lo, seria bom saber exatamente o que está fazendo: $ (($ (data + "% s") - segundos desde 01/01/1970 00:00:00 UTC (Epoch) $ (stat -c "% Y" $ somefile))) - Tempo da última modificação em segundos desde a Época -gt "7200" - verifica se a diferença é maior que x número de segundos.
devo

16

O tempo de criação não é armazenado.

O que são armazenados são três carimbos de data / hora (geralmente, eles podem ser desligados em certos sistemas de arquivos ou por certas opções do sistema de arquivos):

  • Última hora de acesso
  • Hora da última modificação
  • Hora da última mudança

uma "alteração" no arquivo é contada como alterações de permissão, renomeação, etc. Enquanto a modificação é apenas de conteúdo.


12

Embora ctime não seja tecnicamente o momento da criação, frequentemente é.

Como o ctime não é afetado por alterações no conteúdo do arquivo, geralmente só é atualizado quando o arquivo é criado. E sim - posso ouvir vocês gritando - também é atualizado se você alterar as permissões de acesso ou propriedade ... mas geralmente isso é algo que é feito uma vez, geralmente ao mesmo tempo em que coloca o arquivo lá.

Pessoalmente, sempre uso o mtime para tudo e imagino que seja isso que você queira. Mas enfim ... aqui está uma nova versão da festa "nada atraente" de Guss, em uma função fácil de usar.

#! / bin / bash
idade da função () {
   nome do arquivo local = $ 1
   local alterado = `stat -c% Y" $ filename "`
   local agora = `data +% s`
   local decorrido

   deixe decorrido = agora alterado
   echo $ decorrido
}

arquivo = "/"
echo A idade de $ file é $ (idade "$ file") segundos.

Isso foi útil, mas não funcionou imediatamente para OSX porque stat é implementado de forma diferente nele. A única maneira compatível entre sistemas que encontrei foi usando perl. O script deve funcionar em Macs se você substituir a linha correspondente por esta: local changed=$(perl -MFile::stat -e "print stat(\"${filename}\")->mtime") superuser.com/questions/427551/…
Bijou Trouvaille

1
"Tempo de criação" é um conceito difícil de entender. O que isso significa para um arquivo copiado? O que é um arquivo movido? E se ele foi movido para a borda de um dispositivo (de modo que foi criado novamente, em certo sentido)? O que isso significa para um arquivo compactado e posteriormente descompactado? Várias respostas são possíveis aqui e não existe consenso. Mencionar o ctime é bom, mas eu não colocaria semanticamente perto do vago conceito de "tempo de criação". Principalmente porque um simples chmod, aplicado no arquivo, vai anular essa ideia. Mas eu posso viver com você fazendo isso ;-)
Alfe

@Alfe: Você está perdendo o jogo +%sdo segundo tempo
Grizly,

Essa idade pode ser bem menor: age() { echo $(( $(date +%s) - $(date -r "$1" +%s) )); } (Obrigado a @Grizly pela correção!)
Alfe

Na verdade, é melhor usar o tempo de acesso, que é um tempo de criação em todos os sistemas de arquivos montados com noatimeopção (o que é bom para o desempenho, então você deve usá-lo). Portanto, basta usar em %Xvez de %Y.
Nux

7

Encontrar é bom, mas acho que você pode usar de outra maneira, especialmente se você precisar saber agora quantos segundos o arquivo está antigo

date -d "now - $( stat -c "%Y" $filename ) seconds" +%s

usando a data GNU


use gstat, "brew install coreutils"
Erik Johansson

3

Considere o resultado da ferramenta 'stat':

  File: `infolog.txt'
  Size: 694         Blocks: 8          IO Block: 4096   regular file
Device: 801h/2049d  Inode: 11635578    Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/     fdr)   Gid: ( 1000/     fdr)
Access: 2009-01-01 22:04:15.000000000 -0800
Modify: 2009-01-01 22:05:05.000000000 -0800
Change: 2009-01-01 22:05:05.000000000 -0800

Você pode ver aqui as três datas de acesso / modificação / alteração. Não há data de criação. Você só pode ter certeza de quando o conteúdo do arquivo foi modificado (o campo "modificar") ou seu inode mudou (o campo "alterar").

Exemplos de quando ambos os campos são atualizados:

"Modificar" será atualizado se alguém concatenou informações extras ao final do arquivo.

"Alterar" será atualizado se alguém alterar as permissões via chmod.


concedido, stat pode lhe dar informações relevantes. Mas será muito tedioso analisar para obter o que queremos.
PypeBros

0

eu uso

file_age() {
    local filename=$1
    echo $(( $(date +%s) - $(date -r $filename +%s) ))
}

is_stale() {
    local filename=$1
    local max_minutes=20
    [ $(file_age $filename) -gt $(( $max_minutes*60 )) ]
}

if is_stale /my/file; then
    ...
fi
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.