web-dev-qa-db-ja.com

UNIXで2か月前のファイルを削除する方法

以下のログファイルがあるとしましょう。

AA_XX_20130719185428.log
exec_xxx_cpb_20130712182453.log
13122013121327_AR_INC_DOBC_1.dprf.log
24122013_masterscript.LOG

日付部分には、日付と時刻の両方が含まれます。

2か月前のファイルをすべて削除したい。

最終変更日ではなく、ファイル名に含まれている日付に基づいてファイルを削除したくありません。日付は次のいずれかの形式にすることができます。

  • YYYYmmddHHMMSS
  • ddmmYYYYHHMMSS
  • ddmmYYYY。

シェルスクリプトを使用してファイルを削除するにはどうすればよいですか?

3
pankaj

次のスクリプトを使用できます。ファイル名を指定して呼び出し、引数としてテストおよび削除します。

#!/usr/bin/env python
# encoding: utf-8

import os
import sys
import datetime

test_file_names = [x for x in """\
AA_XX_20130719185428.log
exec_xxx_cpb_20130712182453.log
13122013121327_AR_INC_DOBC_1.dprf.log
24122013_masterscript.LOG
""".split('\n') if x.strip()]

# appr. 2 meses
two_months = datetime.date.today() - datetime.timedelta(days=61)

testing = len(sys.argv) < 2
if testing:
    file_names = test_file_names
else:
    file_names = sys.argv[1:]

allow_datetime = set([
    len('YYYYmmddHHMMSS'),
    len('ddmmYYYYHHMMSS'),
    len('ddmmYYYY'),
])

for file_name in test_file_names:
    for part in os.path.splitext(os.path.basename(file_name))[0].split('_'):
        if len(part) not in allow_datetime:
            continue
        for ch in part:
            if not ch.isdigit():
                break
        else:
            dt = part
            if dt[4:6] == '20':  # ddmmYYYY
                yy = int(dt[4:8])
                mm = int(dt[2:4])
                dd = int(dt[:2])
            else:  # YYYYmmdd
                yy = int(dt[:4])
                mm = int(dt[4:6])
                dd = int(dt[6:8])
            try:
                d = datetime.date(yy, mm, dd)
            except ValueError:
                print 'wrong date', yy, mm, dd
                raise
            if testing:
                print '{:<6s} {:<40s} {}'.format(
                    'remove' if d < two_months else ' ', file_name, repr(d))
            Elif d < two_months:
                print 'removing', file_name
                os.remove(file_name)
2
Zelda

GNU dateを使用している場合は、日付操作機能を利用できます。

#!/usr/bin/env bash

## Define the age limit
lim=$(date -d "2 months ago" +%s); 

## Find all files in the current directory and
## sub directories
find . -type f | 

## Extract the longest string of numbers (we assume that is the date)
## and change mmdd to ddmm
Perl -lne '
    ## skip file names that don't have enough numbers 
    /(\d{1,8})/ || next; $d=$1;
    next unless $d;
    ## Change YYYYmmddHHMMSS to mm/dd/YYY 
    if($d=~/201\d$/){$d=~s|(\d{2})(\d{2})(\d{4})|$2/$1/$3|}

    ## Change  ddmmYYYYHHMMSS or ddmmYYYY to mm/dd/YYY 
    else{$d=~s|(\d{4})(\d{2})(\d{2})|$2/$3/$1|}; 

    ## Print the original file name and the modified date string
    print "$_ $d" if 
' | 

## Read the file name into $f and the date into $d
while read f d; do 
## If this date is older than $lim, delete the file
 if [ "$(date -d "$d" +%s)" -lt "$lim" ]; then 
   rm "$f"; 
 fi
done

これは、ターミナルに直接コピーして貼り付けることができる「ワンライナー」に凝縮できます。

lim=$(date -d "2 months ago" +%s); 
find . -type f | Perl -lne '
 /(\d{1,8})/ || next; $d=$1; 
 if($d=~/201\d$/){$d=~s|(\d{2})(\d{2})(\d{4})|$2/$1/$3|}
 else{$d=~s|(\d{4})(\d{2})(\d{2})|$2/$3/$1|}; print "$_ $d"' | 
while read f d; do [ "$(date -d "$d" +%s)" -lt "$lim" ] && echo rm "$f";   done

警告:このソリューションは、ファイル名にスペースが含まれておらず、ファイル名の最長の数字列が常に日付であることを前提としています。

0
terdon