Я снимаю фильмы с интервалом в несколько недель и хочу избавиться от снимков, сделанных ночью (например, с 22:45 до 5:00), как я могу сделать это легко?

Я нашел следующие частичные решения:

  • Использование find -newerXY и, в частности, -newermt было бы возможно, но требует, чтобы я также перебрал все даты,
  • Использование stat для запроса mtime, но я не знаю, как легко сравнить время в bash.

Сейчас я делаю это вручную, но я уверен, что должно быть более элегантное решение. Есть идеи? Спасибо! :)

2 ответа2

1

Эта полу-одиночная строка напечатает "ночные" файлы:

( \
llimit=$((60*5+0)); \
ulimit=$((60*22+45)); \
find -type f -exec bash -c '\
hm=`stat -c "%y" "$0" | cut -c 12-16`; \
t=$((60*10#`echo $hm | cut -c 1-2`+10#`echo $hm | cut -c 4-5`)); \
test \( $t -lt $1 \) -o \( $t -gt $2 \)' \
{} $llimit $ulimit \; \
-print \
)

Подстроки объяснили:

  1. Запускает подоболочку, чтобы сделать переменные локальными.
  2. Вычисляет нижний предел в минутах после полуночи.
  3. Рассчитывает верхний предел.
  4. Для каждого файла выполняется отдельный bash ; это сделает арифметику.
  5. Извлекает mtime как HH:MM .
  6. Преобразует HH:MM в значение в минутах после полуночи.
  7. Сравнивает это значение с предварительно рассчитанными пределами.
  8. Это аргументы для внутреннего bash ; внутри они называются $0 , $1 , $2 .
  9. Печатает путь, если предыдущий тест возвращает true.
  10. Заканчивает подоболочку.

Некоторые замечания:

  • -exec может выступать в качестве теста при вызове find . Это вряд ли очевидно, но очень сильно. В этом случае тест равен true, когда последняя часть внутренней командной строки bash (т. Е. test) возвращает true (т. Е. Его состояние выхода равно 0).
  • Арифметика Bash ( $((…))) анализирует 01 или около того как восьмеричное число, 08 и 09 - недопустимые восьмеричные числа. Вот почему нам нужно использовать 10# чтобы все числа, извлеченные из вывода stat , интерпретировались как десятичные.
  • Я использовал -lt и -gt в test . Используйте -le и / или -ge если они вам больше подходят.
  • Для удаления файлов замените -print на -delete (или используйте их вместе: -print -delete).
  • Чтобы переместить файлы в один каталог, замените -print на -print0 и создайте конвейер следующим образом:

    ( … find … -print0 ) | xargs -0r mv -t /target/directory/
    
1

С помощью stat (предполагается, что все файлы находятся в одном каталоге)

stat -c '%y %n' * | grep -E ' (22:4[5-9]|22:5|23:|0[0-4]:)' | cut -d ' ' -f 4 | xargs mv -t $dirForRemovedFiles
  • это предполагает, что в выходных данных stat не зависит от локали (это, кажется, не ...), в противном случае принудительно установите локаль в "C".
  • это предполагает, что все файлы находятся в одном сегменте DST.
  • обратите внимание на пробел между кавычкой и круглыми скобками, это то, что заставляет регулярное выражение соответствовать только началу метки времени.
  • в целях безопасности приведенная выше команда ничего не удаляет, она просто перемещает файлы в каталог, где вы выдадите команду rm * только вы подтвердите, что ничего не пропустили.
  • если вы параноик, используйте grep -E '^.{10} (22:4[5-9]|22:5|23:|0[0-4]:)' чтобы избежать ложных попаданий.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .