Как я могу найти и удалить файлы на основе даты в сценарии оболочки Linux без поиска? - PullRequest
6 голосов
/ 21 декабря 2011

ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ, ЧТО Я НЕ МОГУ ИСПОЛЬЗОВАТЬ «НАЙТИ» В ЦЕЛЕВОЙ СРЕДЕ

Мне нужно удалить все файлы старше 7 дней в сценарии оболочки linux. Что-то вроде:

FILES=./path/to/dir
for f in $FILES
do
  echo "Processing $f file..."
  # take action on each file. $f store current file name
  # perhaps stat each file to get the last modified date and then delete files with date older than today -7 days.

done

Могу ли я использовать «stat» для этого? Я пытался использовать

find *.gz -mtime +7 -delete

но обнаружил, что я не могу использовать find в целевой системе (нет разрешения для пользователя cron, и это нельзя изменить). Целевой системой является Redhat Enterprise.

Имена файлов имеют следующий формат:

gzip> /mnt/target03/rest-of-path/web/backups/DATABASENAME_date "+%Y-%m-%d".gz

Ответы [ 4 ]

8 голосов
/ 21 декабря 2011

Это должно работать:

#!/bin/sh

DIR="/path/to/your/files"
now=$(date +%s)
DAYS=30

for file in "$DIR/"*
do
    if [ $(((`stat $file -c '%Y'`) + (86400 * $DAYS))) -lt $now ]
    then
    # process / rm / whatever the file...
    fi
done

Немного пояснения: stat <file> -c '%Z' дает время изменения файла в секундах с момента начала UNIX для файла, а $(date +%s) дает текущую метку времени UNIX. Затем нужно просто проверить, больше ли текущая временная метка, чем временная метка файла, плюс семь дней.

3 голосов
/ 22 декабря 2011

Поскольку у вас есть время в имени файла, используйте его для отсчета времени, вот какой-то код, который делает это:

Этот скрипт получает текущее время в секундах с начала эпохи, а затем вычисляет метку времени 7 дней назад. Затем для каждого файла анализирует имя файла и преобразует дату, вставленную в каждое имя файла, в метку времени, а затем сравнивает метки времени, чтобы определить, какие файлы удалить. Использование временных меток избавляет от всех проблем, связанных с работой с датами напрямую (високосный год, разные дни в месяцах и т. Д.)

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

#funciton to get timestamp X days prior to input timestamp
# arg1 = number of days past input timestamp
# arg2 = timestamp ( e.g. 1324505111 ) seconds past epoch
getTimestampDaysInPast () {
    daysinpast=$1
    seconds=$2
    while [ $daysinpast -gt 0 ] ; do
    daysinpast=`expr $daysinpast - 1`
    seconds=`expr $seconds - 86400`
    done
# make midnight
    mod=`expr $seconds % 86400`
    seconds=`expr $seconds - $mod`
    echo $seconds
} 
# get current time in seconds since epoch
getCurrentTime() {
    echo `date +"%s"`
}

# parse format and convert time to timestamp
# e.g. 2011-12-23 -> 1324505111
# arg1 = filename with date string in format %Y-%m-%d
getFileTimestamp () {
    filename=$1
    date=`echo $filename |  sed "s/[^0-9\-]*\([0-9\-]*\).*/\1/g"`
    ts=`date -d $date | date +"%s"`
    echo $ts
}

########################### MAIN ############################
# Expect directory where files are to be deleted to be first 
# arg on commandline. If not provided then use current working
# directory

FILEDIR=`pwd`
if [ $# -gt 0 ] ; then 
    FILEDIR=$1
fi
cd $FILEDIR

now=`getCurrentTime`
mustBeBefore=`getTimestampDaysInPast 7 $now`
SAVEIFS=$IFS
# need this to loop around spaces with filenames
IFS=$(echo -en "\n\b")
# for safety change this glob to something more restrictive
for f in * ; do 
    filetime=`getFileTimestamp $f`
    echo "$filetime lt $mustBeBefore"
    if [ $filetime -lt $mustBeBefore ] ; then
    # uncomment this when you have tested this on your system
    echo "rm -f $f"
    fi
done
# only need this if you are going to be doing something else
IFS=$SAVEIFS
2 голосов
/ 21 декабря 2011

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

is_older(){
    local dtcmp=`date -d "$1" +%Y%m%d`; shift
    local today=`date -d "$*" +%Y%m%d`
    return `test $((today - dtcmp)) -gt 0`
}

и затем вы можете перебирать имена файлов, передавая «-7 дней» в качестве второй даты:

for filename in *;
do
    dt_file=`echo $filename | grep -o -E '[12][0-9]{3}(-[0-9]{2}){2}'`
    if is_older "$dt_file" -7 days; then
        # rm $filename or whatever
    fi
done

В процедуре is_older, date -d "-7 days" +%Y%m%d вернет дату 7 дней назад в числовом формате, готовом для сравнения.

0 голосов
/ 09 июля 2013
DIR=''

now=$(date +%s)

for file in "$DIR/"*
do
echo $(($(stat "$file" -c '%Z') + $((86400 * 7))))
echo "----------"
echo $now

сделано

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...