Как удалить файлы ожидают первый и последний файл по дате изменения в день в папке с bash сценарием оболочки - PullRequest
0 голосов
/ 06 апреля 2020

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

Так я могу удалить все, кроме первого файла за время модификации, но как зарезервировать и последний?

  find /mnt/backups/ -name "db_backup*" -mtime +7 -printf '%TD %TT %p\0' |
  sort -z |
  while IFS= read -r -d '' line
  do
    currentdate=${line%% *}
    if [ "$currentdate" = "$prevdate" ]
    then
      filepath=$(cut -d ' ' -f3- <<< $line)
      rm -- "$filepath"
    fi
    prevdate=$currentdate
  done

Ответы [ 2 ]

0 голосов
/ 06 апреля 2020

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

#!/usr/bin/env bash

root=/mnt/backups # to make it easier for folks to test
prevpath=
while IFS= read -r -d ' ' currdate && IFS= read -r -d '' filepath; do
  if [ "$currdate" = "$prevdate" ]; then
    [[ $prevpath ]] && rm -- "$prevpath"
    prevpath=$filepath
  else
    [[ $prevpath ]] && {
      : "Not deleting: $prevpath"  # for xtrace logging
      prevpath=
    }
  fi
  prevdate=$currdate
done < <(find "$root" -mtime +7 -printf '%TD %p\0' | sort -z)
[[ $prevpath ]] && : "Not deleting: $prevpath" >&2

Если вы запустите bash -x thisscript, вы увидите «Не удалено», зарегистрированное для различных пропускаемых файлов. (Использование < <(...) вместо передачи в l oop гарантирует сохранение переменных, поэтому мы можем записать файл, который не удаляем, в самом конце выполнения).

0 голосов
/ 06 апреля 2020

perl not-so-one-liner, который делает то, что звучит так, как вам нужно - группирует все файлы по дням последней модификации, а затем сортирует файлы каждого дня, чтобы получить все, кроме первого и последнего, каждого дня.

perl -MPOSIX=strftime -E '
  for (glob "*.txt") { # Adjust pattern as needed
    my $mtime = (stat)[9];
    push @{$files{strftime("%Y-%m-%d", localtime $mtime)}}, [ $_, $mtime ]
  }
  for (values %files) {
    my @files = map { $_->[0] } sort { $a->[1] <=> $b->[1] } @$_;
    if (@files > 2) { say for @files[1..$#files-1] }
  }'

После того, как вы проверите и убедитесь, что он печатает только те файлы, которые вы хотите удалить, замените say for на unlink, чтобы фактически удалить их.

...