Bash сравнить даты изменения файлов

Обновлено: 07.07.2024

Я пытаюсь сравнить введенную дату из строк файла журнала с датой вчерашнего дня, и если разница превышает один день, то она печатает эту строку из файла журнала.

Я создал тестовую среду на Windows, используя Cygwin. В Cygwin у меня есть успешный o / p.

Вот исходный код, который я использовал:

Однако при использовании той же команды на главном сервере я получил ошибку:

В поисках ошибки я понял, что это связано с установленными пакетами Solaris

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

Чтобы подтвердить успешное присвоение переменной YESTERDAY:

2 ответа

Ваши форматы даты отличаются между файлом журнала и YESTERDAY , но должны совпадать. Поскольку файл журнала находится в порядке Y-M-D, используйте это:

В моей тестовой системе (также cygwin) это дает те же две строки вывода, которые вы показали в своем вопросе.

Это потому, что awk сравнивает строки, а не даты, поэтому даты должны быть в Y-M-D для числовой сортировки. awk не будет автоматически преобразовывать строку даты в фактическую дату (насколько я знаю). Я добавил скобки в ($1 " " $2) , чтобы уточнить, что вы создаете строку, которая будет сравниваться с другой строкой.

Осторожно . Хотя я считаю, что ваш хак TZ=GMT+20 очень крутой, GMT + 20 опережает МЕТ всего на 19 часов, а не на 24 часа. Следовательно, YESTERDAY не будет установлен правильно, если вы запустите скрипт в неподходящее время суток. Этот ответ содержит пример того, как получить вчерашнюю дату в bash без учета часового пояса.

Как найти вчера?
Из-за перехода на летнее время 24 часа назад может быть сегодня или позавчера. Если вы хотите изменить свой сценарий без использования даты GNU, используйте следующий прием:

Вы уверены, что вчера 20 или 30 часов назад. Который из? Ну, самый последний, которого нет сегодня.

Если вы хотите увидеть разницу в 24 часа (и хотите, чтобы время было включено), используйте что-то вроде

Имейте в виду, что это может быть 23 или 25 часов назад, при переключении DST.

Вот пример того, как я хотел бы использовать это, хотя это не работает как есть:

Как мне достичь желаемого результата?

Что вы хотите зациклить? Вы имеете в виду условный, а не цикл? Почему вы отметили файлы ? Эти даты на самом деле время файла?

Правильный ответ все еще отсутствует:

Не знаю, почему кто-то опроверг это, он довольно точен и не связан с объединением некрасивых строк. Преобразуйте дату в метку времени Unix (в секундах), сравните метки времени Unix. Я думаю, для меня главное преимущество этого решения в том, что вы можете легко делать сложения или вычитания. Например, я хотел, чтобы время ожидания составляло x секунд, но моя первая идея ( timeout=$(`date +%Y%m%d%H%M%S` + 500) ) явно неверна. Вы можете включить точность наносекунд с date -d 2013-07-18 +%s%N

Вам не хватает формата даты для сравнения:

Вам тоже не хватает циклических структур, как вы планируете получать больше дат?

date -d не является стандартным и не работает на типичной UNIX. На BSD он даже пытается установить значение кенеля DST .

Можно использовать стандартное сравнение строк для сравнения хронологического порядка [строк в формате год, месяц, день].

К счастью, когда [строки, которые используют формат YYYY-MM-DD] сортируются * в алфавитном порядке, они также сортируются * в хронологическом порядке.

(* - отсортировано или сравнено)

Ничего особенного в этом деле не нужно. ура!

Это единственное решение, которое работало для меня на Sierra MacOS Это проще, чем мое решение if [ $(sed -e s/-//g <<< $todate) -ge $(sed -e s/-//g <<< $cond) ]; . Этот формат даты был разработан для сортировки с использованием стандартной буквенно-цифровой сортировки или для - сортировки и численной сортировки.

Это проблема не циклических структур, а типов данных.

Эти даты ( todate и cond ) являются строками, а не числами, поэтому вы не можете использовать оператор "-ge" для test . (Помните, что обозначение в квадратных скобках эквивалентно команде test .)

Что вы можете сделать, это использовать другую запись для ваших дат, чтобы они были целыми числами. Например:

выдаст целое число, например 20130715, 15 июля 2013 г. Затем вы сможете сравнить свои даты с "-ge" и эквивалентными операторами.

Обновление: если указаны ваши даты (например, вы читаете их из файла в формате 2013-07-13), то вы можете легко предварительно обработать их с помощью tr.

Оператор -ge работает только с целыми числами, которых нет у ваших дат.

Если ваш скрипт представляет собой скрипт bash или ksh или zsh, вы можете использовать < вместо этого оператор. Этот оператор недоступен в тире или других оболочках, которые не выходят за рамки стандарта POSIX.

В любой оболочке вы можете преобразовать строки в числа, соблюдая порядок дат, просто удалив тире.

Кроме того, вы можете перейти на традиционные и использовать expr утилиту.

Поскольку запуск подпроцессов в цикле может быть медленным, вы можете предпочесть выполнить преобразование, используя конструкции обработки строки оболочки.

Конечно, если вы можете получить даты без дефисов, вы сможете их сравнить -ge .

У меня есть папка с кучей подпапок, эти папки asciidoctor отформатированы с .adoc расширением.

Каждый раз, когда я вносил изменения в файлы (что часто), мне нужно запустить

скомпилировать его в формат HTML.

Я пытаюсь автоматизировать процесс. до сих пор я пришел с этим с помощью entr :

но работает только с существующей папкой не для подпапок. Я пробовал этот вариант, но он не работает:

Любые идеи, как я мог бы реализовать этот процесс автоматизации для всех вложенных папок?

Linux предоставляет удобный интерфейс для мониторинга всех событий файловой системы, таких как создание, изменение, удаление файлов. Интерфейс представляет собой inotify семейство системных вызовов, утилиты пользовательского пространства, использующие эти вызовы, предоставляются inotify-tools пакетом в Ubuntu (доступно в репозитории юниверсов). Если у вас его еще нет, установите:

inotify-tools предоставляет inotifywait и inotifywatch двоичные файлы, нам нужен первый.

Таким образом, вы хотите выполнить команду, asciidoctor -q some_file когда какой-либо .adoc файл будет изменен ( some_file будет заменен этим), если, если это так, если ваши .adoc файлы находятся в каталоге /foo/bar , вы можете установить часы:

-q включает тихий режим, никакой информации от inotifywait себя

-m включает режим мониторинга, иначе он выйдет после первого события

--event modify , нас интересует только modify событие, то есть когда файл изменяется. Другие возможные значения включают open и close т. Д.

--format %w , мы хотим, чтобы имя файла было изменено, а не куча другой информации, так как мы будем использовать имя файла в качестве ввода для другой команды

/foo/bar/*.adoc будет расширен до всех .adoc файлов в /foo/bar каталоге

Теперь вышеприведенное покажет вам имя файла, когда что-либо будет изменено, теперь для запуска команды с именем файла (при условии, что команда принимает аргументы через STDIN):

Вы также можете установить рекурсивное наблюдение за каталогом, которое вам нужно будет использовать grep для фильтрации только нужных файлов. Здесь установка watch recursively ( -r ) на каталог /foo/bar и использование grep для фильтрации только .adoc файлов:

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

Обратите внимание, что вы также можете работать inotifywait в режиме daemon ( -d ), вы также можете создавать сценарии целиком и / или работать в фоновом режиме, и / или играть с другими дополнительными параметрами.

Кроме того, вы можете заменить asciidoctor любую другую команду по вашему выбору, если хотите.

Система РедХат 6




date +%m/%d/%Y

И приведенный пример считает разницу в секундах, а не в месяцах.

А в месяцах можно считать двояко. Можно в секундах, затем делить на 30 дней:


Но, ИМХО, так не совсем правильно. Особенно ошибка будет заметна на больших диапазонах.
Я бы отдельно считал разницу в годах, отдельно в месяцах:
Kroz ★★★★★ ( 31.12.15 14:47:17 )
Последнее исправление: Kroz 31.12.15 14:48:01 (всего исправлений: 1)


Переводить в Epoch, разность делить до нужной точности.

А зачем вообще все эти date и прочие сложности? Количество месяцев в любом году же, вроде бы, постоянно, не?


Необходимо получить разницу в количестве месяцев между двумя датами вида dd/mm/yyyy

А скорость получения важна? :-)

Или я задачу не понял? Судя по тому, как тут все ее серьезно обсуждают, это весьма возможно.

Zmicier ★★★★★ ( 31.12.15 16:36:45 )
Последнее исправление: Zmicier 31.12.15 16:39:05 (всего исправлений: 1)


Если (текущая дата - дата сертификата из токена > 14 месяцев) то слать емыл админу что в сервере hostname срок действия сертификата, через месяц закончится. иначе Если (текущая дата - дата сертификата из токена > 15 месяцев) то слать емыл админу что в сервере hostname срок действия сертификата уж кончился.

Скрипт засовывается в крон, и раз в день исполняется. Цель всего, заблаговременно понять что сертификат скоро кончится и нужно его перевыпустить.

Читайте также: