开发者

bash script to find old files based off date in file name

I'm developing a bash script that needs to search out files within a single directory that are "old" based off a variable that specifies how 开发者_如何学编程many days need to pass before the threshold is exceeded and the files are marked for action (could be anything from move to archive to delete, etc...).

The catch is that the modify time of the file is irrelevant in determining how old the files need to be before taken action upon, as the files may infrequently be changed, the execution time of the script can vary, etc...

The time that determines hold the files are is in the actual file name in the form of YYYY-MM-DD (or %F with the date command). take for instance the filename contents-2011-05-23.txt. What command(s) could be run in this directory to find all files that exceed a certain amount of days (I have the threshold currently set to 7 days, could change) and print out their file names?


Create a bash script isOld.sh like this:

#!/bin/bash

fileName=$1
numDays=$2

fileDt=$(echo $fileName | sed 's/^[^-]*-\([^.]*\)\..*$/\1/')
d1=$(date '+%s')
d2=$(date -d $fileDt '+%s')
diff=$((d1-d2))
seconds=$((numDays * 24 * 60 * 60))
[[ diff -ge seconds ]] && echo $fileName

Then give execute permission to above file by running:

chmod +x ./isOld.sh

And finally run this find command from top of your directory to print files older than 7 days as:

find . -name "contents-*" -exec ./isOld.sh {} 7 \;


In BSD, the -j is used to prevent the date being set and the -f parameter is used to set the format of the input date. :

First, you need to find today's date in the number of days since January 1, 1970:

 today=$(date -j -f "%Y-%m-%d" 1969-12-31 +%s)

Now, you can use that to find out the time seven days ago:

 ((cutoff = $today - 604800))

The number 604800 is the number of seconds in seven days.

Now, for each file in your directory, you need to find the date part of the string. I don't know of a better way. (Maybe someone knows some Bash magic).

find . -type f | while read fileName
do
     fileDate=$(echo $foo | sed 's/.*-\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\).*/\1/')
     yadda, yadda, yadda #Figure this out later
done

Once we have the file date, we can use the date command to figure out if that date in seconds in less than (and thus older than the cutoff date)

today=$(date -j -f "%Y-%m-%d" 1969-12-31 +%s)
((cutoff = $today - 604800))
find . -type f | while read fileName  #Or however you get all the file names
do
     fileDate=$(echo $foo | sed 's/.*-\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\).*/\1/')
     fileDateInSeconds=$(date -j -f "%Y-%m-%d" $fileDate +%s)
     if [ $fileDateInSeconds -lt $cutoff ]
     then
          rm $fileName
     fi
done

In Linux, you use the -d parameter to define the date which must be in YYYY-MM-DD format:

today=$(date +"%Y-%m-%d)

Now, you can take that and find the number of seconds:

todayInSeconds=(date -d $today +%s)

Everything else should be more or less the same as above.


If you run the command daily, you could do this:

echo *-`date -d '8 days ago' '+%F'`.txt

Additional wildcards could be added ofcourse


find *[0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]*.txt -exec bash -c 'dt=`echo $0 | sed -re "s/.*([0-9]{4}-[0-9]{2}-[0-9]{2}).*/\1/"`; file_time=`date -d $dt +%s`; cutoff_time=`date -d "31 days ago" +%s` ; test $file_time -lt $cutoff_time ' {} \; -print

That's one of my longest one liners :-) Here it is again wrapped:

find *[0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]*.txt \
  -exec bash -c ' dt=`echo $0 | \
                  sed -re "s/.*([0-9]{4}-[0-9]{2}-[0-9]{2}).*/\1/"`; \
                  file_time=`date -d $dt +%s`; \
                  cutoff_time=`date -d "31 days ago" +%s` ;\
                  test $file_time -lt $cutoff_time \
                ' {} \; -print
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜