Назад | Перейти на главную страницу

Удалять все файлы, кроме самого нового, каждого дня

У меня есть каталог дампов, который регулярно обновляется.

Я хочу удалить все файлы старше одной недели.

Bash предпочтительнее, хотя приветствуются и другие решения.

Хитрость в том, --full-time флаг, который может быть передан ls команда, которая возвращает список файлов с очень легко настраиваемыми полями даты. Мы легко можем отсортировать его по дате.

$ ls -l --full-time|sort -k +7
-rwxr-xr-x  1 cica cica  16536 2014-07-10 10:47:32.448349200 +0200 epl-v10.html
-rwxr-xr-x  1 cica cica   9013 2014-07-10 10:47:32.495149500 +0200 notice.html
drwxr-xr-x+ 1 cica cica      0 2014-07-07 14:12:11.502336700 +0200 readme
drwxr-xr-x+ 1 cica cica      0 2014-07-31 14:38:20.800181400 +0200 p2
drwxr-xr-x+ 1 cica cica      0 2014-07-31 15:15:06.506730000 +0200 features
drwxr-xr-x+ 1 cica cica      0 2014-07-31 15:15:06.680747400 +0200 plugins
-rw-r--r--  1 cica cica 368634 2014-07-31 15:15:06.826762000 +0200 artifacts.xml
-rw-r--r--  1 cica cica    329 2014-07-31 15:15:12.816360900 +0200 eclipse.ini
-rwxr-xr-x  1 cica cica   7929 2014-07-14 16:01:58.698363500 +0200 system_catalog.xml
drwxr-xr-x+ 1 cica cica      0 2014-07-31 17:41:59.205940000 +0200 configuration
-rwxr-xr-x  1 cica cica 312320 2014-06-01 20:12:16.000000000 +0200 eclipse.exe
-rwxr-xr-x  1 cica cica  17920 2014-06-01 20:12:16.000000000 +0200 eclipsec.exe

Сначала сортируем по то полный Дата!

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

Во-вторых, мы добрались до простого сценария awk: awk '{if ($6 == EX) print $9; EX=$6}'

Наконец, мы используем xargs чтобы разрешить удаление каждого файла с rm команда.

Полная команда:

ls -l --full-time|sort -k +6|awk '{if ($6 == EX) print $9; EX=$6}'|xargs -P 1 -n 1 echo rm -vf

Эту команду нужно вызывать периодически, в идеале из cron. В идеале вы можете сдаться crontab -e, вы звоните по этому номеру каждый день в 2:37:

37 2 * * *     ls -l --full-time|sort -k +6|awk '{if ($6 == EX) print $9; EX=$6}'|xargs -P 1 -n 1 echo rm -vf

Конечно, вы можете поместить это в скрипт и вызывать только скрипт из cron.

Я искал подобное, но ничего не нашел, написал свой сценарий, который это делает. У меня довольно мало опыта работы с bash, так что это, вероятно, можно было бы сделать намного чище и быстрее, но это сработало для меня. Я понимаю, что это довольно старый вопрос, но все же хотел на него ответить.

Что делает этот конкретный сценарий:

  • Безвозвратно удаляет файлы старше full_delete.
  • Для файлов старше, чем 'partial_delete', использовать самую последнюю за день.
  • Сохраните все остальные файлы

Оптимизация, которая могла быть сделана, - это изменить жесткое удаление, чтобы просто использовать find с флагами delete и mtime, но я хотел сохранить все это вместе.

#!/bin/bash

full_delete=$((60 * 60 * 24 * 30)) # 30 days
partial_delete=$((60 * 60 * 24 * 5)) # 5 days

for filename in ./data/*; do
  # Check if file still exists, partial delete might've nuked it
  if [ -f "$filename" ]; then

    # Get epoch diff between now and when it was last modified
    since_modified_epoch=$(( $(date +%s) - $(stat -L --format %Y "$filename") ))

    # File is past our hard threshold, just remove
    if [ $since_modified_epoch -gt $full_delete ]; then
      rm "$filename"

    elif [ $since_modified_epoch -gt $partial_delete ]; then
      # Y-m-D file was modified
      modified_date=$(date +%Y-%m-%d -r "$filename")
      # Y-m-D file was modified + 1 day
      modified_date_plus=$(date +%Y-%m-%d -d "$modified_date +1 days")
      # Get all files where modified date is between previous 2 dates
      # 'head -n -1' ignores the newest file
      partial_files=$( find ./backups/ -type f -newermt "$modified_date" -not -newermt "$modified_date_plus" -printf "%T+§%p\\n" | sort | head -n -1 )

      for partial_file in $partial_files; do
        # Extract just filename from the line
        partial_to_delete=$( echo "$partial_file" | cut -d'§' -f 2 )
        rm "$partial_to_delete"
      done;
    fi
  fi
done

Код, который можно использовать для создания тестового примера. В результате будут созданы файлы с 4-часовым интервалом на 40 дней.

#!/bin/bash
rm -rf ./data
mkdir -p data

for i in $(seq 1 $(( 40 * (24 / 4) )) ); do
  amount=$(( i * 4 * 60 ))
  touch -d "$amount minutes ago" "./data/data_$i";
done

Хитрость в том, --full-time флаг, который может быть передан ls команда, которая дает bacvk список файлов с очень хорошими полями даты, доступными через скрипт:

$ ls -l --full-time|sort -k +7
-rwxr-xr-x  1 cica cica  16536 2014-07-10 10:47:32.448349200 +0200 epl-v10.html
-rwxr-xr-x  1 cica cica   9013 2014-07-10 10:47:32.495149500 +0200 notice.html
drwxr-xr-x+ 1 cica cica      0 2014-07-07 14:12:11.502336700 +0200 readme
drwxr-xr-x+ 1 cica cica      0 2014-07-31 14:38:20.800181400 +0200 p2
drwxr-xr-x+ 1 cica cica      0 2014-07-31 15:15:06.506730000 +0200 features
drwxr-xr-x+ 1 cica cica      0 2014-07-31 15:15:06.680747400 +0200 plugins
-rw-r--r--  1 cica cica 368634 2014-07-31 15:15:06.826762000 +0200 artifacts.xml
-rw-r--r--  1 cica cica    329 2014-07-31 15:15:12.816360900 +0200 eclipse.ini
-rwxr-xr-x  1 cica cica   7929 2014-07-14 16:01:58.698363500 +0200 system_catalog.xml
drwxr-xr-x+ 1 cica cica      0 2014-07-31 17:41:59.205940000 +0200 configuration
-rwxr-xr-x  1 cica cica 312320 2014-06-01 20:12:16.000000000 +0200 eclipse.exe
-rwxr-xr-x  1 cica cica  17920 2014-06-01 20:12:16.000000000 +0200 eclipsec.exe

Сначала сортируем по то полный Дата!

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

Во-вторых, мы добрались до простого сценария awk: awk '{if ($6 == EX) print $9; EX=$6}'

Наконец, мы используем xargs чтобы разрешить удаление каждого файла с rm команда.

Полная команда:

ls -l --full-time|sort -k +6|awk '{if ($6 == EX) print $9; EX=$6}'|xargs -P 1 -n 1 echo rm -vf

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

find <path of file> -typf f -mtime +0 -exec rm {} \;

он удалит файлы, датированные вчера.