如何在没有查找的情况下在 linux shell 脚本中根据日期查找和删除文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8593171/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 03:46:07  来源:igfitidea点击:

How can I find and delete files based on date in a linux shell script without find?

linuxbashshell

提问by codecowboy

PLEASE NOTE THAT I CANNOT USE 'find' IN THE TARGET ENVIRONMENT

请注意,我无法在目标环境中使用“查找”

I need to delete all files more than 7 days old in a linux shell script. SOmething like:

我需要删除 linux shell 脚本中超过 7 天的所有文件。就像是:

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

Can I use 'stat' to do this? I was trying to use

我可以使用'stat'来做到这一点吗?我试图使用

find *.gz -mtime +7 -delete

but discovered that I cannot use find on the target system (there is no permission for the cron user and this can't be changed). Target system is Redhat Enterprise.

但发现我无法在目标系统上使用 find (cron 用户没有权限,无法更改)。目标系统是 Redhat Enterprise。

The file names are formatted like this:

文件名的格式如下:

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

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

采纳答案by Cjolly

Since you have time in the filename then use that to time the deletion heres some code that does that :

由于您在文件名中有时间,因此可以使用它来计时删除这里的一些代码:

This script gets the current time in seconds since epoch and then calculates the timestamp 7 days ago. Then for each file parses the filename and converts the date embeded in each filename to a timestamp then compares timestamps to determine which files to delete. Using timestamps gets rid of all hassles with working with dates directly (leap year, different days in months, etc )

此脚本获取自纪元以来的当前时间(以秒为单位),然后计算 7 天前的时间戳。然后为每个文件解析文件名并将嵌入在每个文件名中的日期转换为时间戳,然后比较时间戳以确定要删除的文件。使用时间戳可以摆脱直接处理日期的所有麻烦(闰年、月份中的不同天数等)

The actual remove is commented out so you can test the code.

实际删除被注释掉,以便您可以测试代码。

#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=
    seconds=
    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=
    date=`echo $filename |  sed "s/[^0-9\-]*\([0-9\-]*\).*//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=
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

回答by pgl

This should work:

这应该有效:

#!/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

A bit of explanation: stat <file> -c '%Z'gives the modification time of the file as seconds since the UNIX epoch for a file, and $(date +%s)gives the current UNIX timestamp. Then there's just a simple check to see whether the file's timestamp, plus seven days' worth of seconds, is greater than the current timestamp.

稍微解释一下:stat <file> -c '%Z'将文件的修改时间作为自文件的 UNIX 纪元以来的秒数,并$(date +%s)给出当前的 UNIX 时间戳。然后只需简单检查文件的时间戳,加上 7 天的秒数,是否大于当前时间戳。

回答by Elias Dorneles

If you prefer to rely on the date in the filenames, you can use this routine, that checks if a date is older than another:

如果你更喜欢依赖文件名中的日期,你可以使用这个例程,检查一个日期是否比另一个更旧:

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

and then you can loop through filenames, passing '-7 days' as the second date:

然后您可以遍历文件名,将“-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

In is_olderroutine, date -d "-7 days" +%Y%m%dwill return the date of 7 days before, in numeric format ready for the comparison.

is_older例程中,date -d "-7 days" +%Y%m%d将返回 7 天前的日期,以数字格式准备好进行比较。

回答by Piyush Wandhare

DIR=''

now=$(date +%s)

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

done

完毕