2011-12-21 32 views
6

XIN LƯU Ý RẰNG TÔI CÓ THỂ KHÔNG SỬ DỤNG 'tìm' TRONG MỤC TIÊU MÔI TRƯỜNGLàm cách nào để tìm và xóa tệp dựa trên ngày trong tập lệnh shell linux mà không tìm thấy?

tôi cần phải xóa tất cả các file hơn 7 ngày tuổi trong một kịch bản shell Linux. SOmething like:

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 

Tôi có thể sử dụng 'stat' để làm điều này không? Tôi đã cố gắng sử dụng

find *.gz -mtime +7 -delete 

nhưng phát hiện ra rằng tôi không thể sử dụng tìm thấy trên hệ thống mục tiêu (không có sự cho phép cho người sử dụng cron và điều này không thể thay đổi). Hệ thống đích là Redhat Enterprise.

Các tên tập tin được định dạng như thế này:

gzip>/mnt/target03/phần còn lại-of-path/web/backups/DATABASENAME_ date "+%Y-%m-%d" gz

Trả lời

3

Kể từ khi bạn có thời gian trong tên tập tin sau đó sử dụng để thời gian xóa heres một số mã nào đó:

Kịch bản này được thời gian hiện tại trong vài giây kể từ kỷ nguyên và sau đó tính toán dấu thời gian 7 ngày trước. Sau đó, cho mỗi tệp phân tích tên tệp và chuyển đổi ngày được nhúng trong mỗi tên tệp thành dấu thời gian, sau đó so sánh dấu thời gian để xác định tệp cần xóa. Sử dụng dấu thời gian sẽ loại bỏ mọi phức tạp khi làm việc với ngày trực tiếp (năm nhuận, các ngày khác nhau trong tháng, v.v.)

Loại bỏ thực tế được nhận xét để bạn có thể kiểm tra mã.

#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 
+0

Tôi có cố gắng sử dụng mã này, nhưng chỉ nhận được kết quả này: 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 lt 1324944000 1325559635 lt 1324944000 1325559635 lt 1324944000 1325559635 lt 1324944000 – codecowboy

+0

Các echo "rm -f $ f" không bao giờ có vẻ chạy. Các tệp được đặt tên như thế này - eeSwap_2011-12-20.gz. Regex có bắt được tên tập tin này một cách chính xác không? – codecowboy

+0

Hóa ra ts = 'date -d $ date | date + "% s" 'phải là ts =' date -d "$ date" + "% s" 'Tập lệnh sau đó hoạt động – codecowboy

8

này nên làm việc:

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

Một chút giải thích: stat <file> -c '%Z' cung cấp thời gian sửa đổi của tệp là giây kể từ kỷ nguyên UNIX cho một tệp và $(date +%s) cung cấp dấu thời gian UNIX hiện tại. Sau đó, chỉ có một kiểm tra đơn giản để xem liệu dấu thời gian của tệp, cộng với giá trị của bảy ngày có lớn hơn dấu thời gian hiện tại hay không.

+0

Cảm ơn - đang nhận lỗi về một thiếu ')'. Nên $ bây giờ cũng có trong dấu ngoặc kép? Tôi đang đặt $ (rm "$ tập tin"), nơi bình luận của bạn là. – codecowboy

+0

Bạn chỉ cần đặt 'rm '$ file" ' – pgl

+0

@pgl Cảm ơn kịch bản tuyệt vời này, nhưng nó không hoạt động trên busybox, nó cần phải được mát xa một chút vì vậy đây là cách nó làm việc ra hình thức tôi: '#!/ Bin/sh DIR = "/ path/to/your/file" tại = $ (date +% s) NGÀY = 30 for file in "$ DIR /" * làm nếu [$ ((('stat $ file -c '% Y'') + (86400 * $ DAYS))) -lt $ now] rồi # process/rm/bất cứ tập tin nào ... fi done' – valentt

2

Nếu bạn muốn dựa vào các ngày trong tên tập tin, bạn có thể sử dụng thói quen này, để kiểm tra nếu một ngày là lớn hơn khác:

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

và sau đó bạn có thể lặp qua tên tập tin, đi qua '- 7 ngày là ngày thứ hai:

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 

trong is_older thói quen, date -d "-7 days" +%Y%m%d sẽ trở lại ngày 7 ngày trước đó, ở định dạng số sẵn sàng cho việc so sánh.

0
DIR='' 

now=$(date +%s) 

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

làm

Các vấn đề liên quan