как мне проверить в bash, был ли файл создан более x раз назад?


106

Я хочу проверить в linux bash, был ли файл создан более x раз назад.

скажем, файл называется text.txt и время составляет 2 часа.

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

Ответы:


139

Только на время модификации

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

Вы можете использовать -cminдля изменения или -aminдля времени доступа. Как указывали другие, я не думаю, что вы можете отслеживать время создания.


3
вы можете отбросить «тест» и обратные кавычки. Это аналогично if (test == true) vs if (test)
guns

2
Вы правы; Я полагаю, я думал, что findвернул ненулевое значение, когда совпадений не найдено.
guns

4
Вы можете отбросить обратные кавычки и сделать if test $ (find text.txt -mmin +120)
tommy.carstensen

1
@BroSlow выглядит лучше: не может быть "более одного". Конечно, text.txtпредполагается, что это не каталог.
kmkaplan

2
Я предпочитаю этот синтаксис:[ "$(find path/to/file -mmin +120)" ] && echo "it is old"
Alfe 01

42

Мне всегда нравилось использовать, date -r /the/file +%sчтобы узнать свой возраст.

Вы также можете сделать touch --date '2015-10-10 9:55' /tmp/fileочень точное время в произвольную дату / время.


Я искал сегодня то же самое. Лучший!
Умайр А. 04

Спасибо. Я натолкнулся на этот ТАК вопрос, потому что я погуглил «как напечатать возраст файла bash». Так что это именно то, что я искал!
Ной Сассман

5
Спасибо! с единственной оговоркой, что указанное выше является меткой времени (не возрастом), но может использоваться для вычисления возраста подобным образом let AGE=$(($(date +%s)-$(date -r /path/to/file +%s))) [с допущением, что создавалось и никогда не
изменялось

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

1
@turiyag Обязательное примечание, то $[ ]есть, если оно не устарело , то по крайней мере устаревшее и менее переносимое , и $(( ))вместо него следует использовать ; и обратные кавычки более хрупкие, чем $( ); а также дефисы в именах функций могут быть не полностью переносимы. Но суть в этом хорошая!
michaelb958 - GoFundMonica

23

Используя statдля определения даты последней модификации файла, dateдля определения текущего времени и свободного использования bashisms, можно выполнить тест, который вы хотите, на основе времени последнего изменения файла 1 .

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

Хотя код немного менее читабелен, чем этот findподход, я думаю, что это лучший подход, чем findпросмотр файла, который вы уже «нашли». Кроме того, манипуляции с датами - это весело ;-)


  1. Как правильно заметил Фил, время создания не записывается, но используйте %Zвместо этого, %Yуказанное ниже, чтобы получить «время изменения», которое может быть тем, что вы хотите.

[Обновить]

Для пользователей Mac используйте stat -f "%m" $somefileвместо синтаксиса Linux, указанного выше


В какую оболочку встроены дата и статистика? В моем bash (GNU, 3.2.48) их нет.
Ян Клелланд,

ой, извини. statне встроен - очень плохо с моей стороны, исправлю.
Guss,

1
Правильное решение @Guss - установить coretutils с помощью brew. :-)
Эрик Йоханссон

1
@ErikJohansson Я предпочитаю не требовать установки дополнительного программного обеспечения, когда существующее работает нормально - это не Windows, вы знаете ;-)
Гасс

1
Для людей, которые хотят использовать это, но изменить его, было бы хорошо знать, что именно он делает: $ (($ (date + "% s") - секунды с 1970-01-01 00:00:00 UTC (Epoch) $ (stat -c "% Y" $ somefile))) - Время последней модификации в секундах после Epoch -gt "7200" - проверяет, больше ли разница, чем x количество секунд.
DevO

16

Время создания не сохраняется.

В памяти хранятся три метки времени (обычно они могут быть отключены в определенных файловых системах или с помощью определенных параметров файловой системы):

  • Время последнего доступа
  • Время последней модификации
  • Время последнего изменения

«Изменение» файла засчитывается как изменение разрешений, переименование и т. д. Хотя изменение относится только к содержимому.


12

Хотя ctime технически не является временем создания, это довольно часто бывает.

Поскольку ctime на него не влияют изменения содержимого файла, обычно оно обновляется только при создании файла. И да - я слышу, как вы все кричите - он также обновляется, если вы меняете права доступа или владельца ... но обычно это то, что делается один раз, обычно в то же время, когда вы помещаете туда файл.

Лично я всегда использую mtime для всего, и я думаю, что это то, что вы хотите. Но в любом случае ... вот переработка «непривлекательного» bash Гуса в простой в использовании функции.

#! / bin / bash
function age () {
   локальное имя файла = $ 1
   локально изменено = `stat -c% Y" $ filename "`
   местное сейчас = `дата +% s`
   местное истекло

   let elapsed = теперь-изменено
   echo $ elapsed
}

file = "/"
echo Возраст $ file составляет $ (age "$ file") секунд.

Это было полезно, но не сразу сработало для OSX, потому что stat реализован в нем по-другому. Единственный способ, который я нашел для кросс-системной совместимости, - это использование perl. Скрипт должен работать на Mac, если вы замените соответствующую строку на это: local changed=$(perl -MFile::stat -e "print stat(\"${filename}\")->mtime") superuser.com/questions/427551/…
Bijou Trouvaille

1
«Время творения» - понятие, которое трудно понять. Что это значит для скопированного файла? Что за перемещаемый файл? Что, если бы он был перемещен через границу устройства (в некотором смысле, он был создан заново)? Что это означает для запакованного, а затем неупакованного файла? Здесь возможно несколько ответов, и единого мнения нет. Хотя упоминание ctime - это хорошо, но я бы не стал семантически приближать его к расплывчатому понятию «время создания». Тем более, что простая chmod, примененная к файлу, сводит на нет эту идею. Но я могу жить с тобой, делая это ;-)
Alfe

@Alfe: Вы упускаете +%sиз виду второй тайм
Grizly

Этот возраст может быть намного короче: age() { echo $(( $(date +%s) - $(date -r "$1" +%s) )); } (Спасибо @Grizly за исправление!)
Alfe

На самом деле лучше использовать время доступа, которое является временем создания для всех файловых систем, смонтированных с noatimeопцией (что хорошо для производительности, поэтому вы должны использовать его). Так что просто используйте %Xвместо %Y.
Nux

7

Найти один хороший, но я думаю, вы можете использовать другой способ, особенно если вам нужно сейчас, сколько секунд старый файл

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

используя дату GNU


используйте gstat, «brew install coreutils»
Эрик Йоханссон,

3

Рассмотрим результат работы инструмента 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

Здесь вы можете увидеть три даты для доступа / изменения / изменения. Дата создания отсутствует. Вы можете быть уверены только в том, что содержимое файла было изменено (поле «изменить») или его индексный дескриптор (поле «изменить»).

Примеры обновления обоих полей:

«Изменить» будет обновлено, если кто-то добавил дополнительную информацию в конец файла.

«Изменить» будет обновлено, если кто-то изменил права доступа через chmod.


Если да, stat может предоставить вам соответствующую информацию. Но это будет довольно утомительно разбирать, чтобы получить то, что мы хотим.
PypeBros

0

я использую

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.