【问题标题】:How can I find and delete files based on date in a linux shell script without find?如何在不查找的情况下在 linux shell 脚本中根据日期查找和删除文件?
【发布时间】:2011-12-21 16:37:26
【问题描述】:

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

我需要删除 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

我可以使用“stat”来执行此操作吗?我正在尝试使用

find *.gz -mtime +7 -delete

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

文件名的格式如下:

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

【问题讨论】:

    标签: linux bash shell


    【解决方案1】:

    这应该可行:

    #!/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 时间戳。然后只需简单检查文件的时间戳加上 7 天的秒数是否大于当前时间戳。

    【讨论】:

    • 谢谢 - 我收到关于缺少 ')' 的错误。 $now 也应该用引号引起来吗?我将 $(rm "$file") 放在您的评论所在的位置。
    • 你应该只需要输入rm "$file"
    • @pgl 感谢这个很棒的脚本,但它在busybox上不起作用,它需要稍微调整一下,所以这是我的结果:#!/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
    【解决方案2】:

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

    此脚本获取自纪元以来的当前时间(以秒为单位),然后计算 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
    

    【讨论】:

    • 我已经使用该代码,但只得到这样的输出的尝试:1325559634 LT 1324944000 1325559634 LT 1324944000 1325559635 LT 1324944000 1325559635 LT 1324944000 1325559635 LT 1324944000 1325559635 LT 1324944000 1325559635 LT 1324944000 1325559635 LT 1324944000 1325559635 LT 1324944000 1325559635 LT 1324944000 1325559635 1324944000 1325559635 1324944000 1325559635 1324944000 1325559635 1324944000
    • echo "rm -f $f" 似乎永远不会运行。文件命名如下 - eeSwap_2011-12-20.gz。正则表达式会正确捕获此文件名吗?
    • 原来 ts=date -d $date | date +"%s" 应该是 ts=date -d "$date" +"%s" 脚本才起作用
    【解决方案3】:

    如果您更喜欢依赖文件名中的日期,您可以使用此例程来检查日期是否早于另一个日期:

    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 天前的日期,以供比较。

    【讨论】:

      【解决方案4】:
      DIR=''
      
      now=$(date +%s)
      
      for file in "$DIR/"*
      do
      echo $(($(stat "$file" -c '%Z') + $((86400 * 7))))
      echo "----------"
      echo $now
      

      完成

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-13
        • 2011-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多