# comparing current date to modified date



## cgjoker (Aug 13, 2003)

Got another...

How can I compare a modification date of a file, plus say 10 days, and if it equals the current date then move the file?

So...

for file in *
do
curdate=`date +%b +%d`
moddate=`ls -l|grep {files modification date}
if ${moddate} <= 1${curdate} + 10`
then
mv ${file} ./directory/. 
fi
done


----------



## AGCurry (Jun 15, 2005)

Everything you need is provided in the "find" command.

Do "man find" to learn more.


----------



## cgjoker (Aug 13, 2003)

Thanks but im not looking for instructions on how to use the find command, im trying to find out how to compare a modified date of a file with a current date. Im not looking for files with a specific modified date.

I would imagine the script would look something like this...

flag=14
cd olddirectory
for file in `ls -l *`
do
if -mtime {$flag} <= `date`
then 
mv $file /directory/.
fi


----------



## AGCurry (Jun 15, 2005)

In the past I've written my own C programs to do things like this, as I don't believe you can do exactly what you're describing with pure shell scripts.

However, alternatively you can use the touch command to set the mtime of a specific file, and then use test with the -nt or -ot option:

cd olddirectory
touch -m -t 200509011200 ref_file # Sept 1, 2005, noon
for file in *
do
if [ $file -ot ref_file ]
then
mv $file /directory/.
fi
done


----------



## cgjoker (Aug 13, 2003)

I see how this would work, but unfortunately it doesn't really apply to what im trying to do.

I will not have the novelty of specifying a particular day because this would run every day. I suppose I can substitute the static date with a unix 'date' command. Is there a way I can say, 
if [ $file -ot ref_file "by x number of days"]
do 
......

?

thanks for your help with this.
c.


----------



## Squashman (Apr 4, 2003)

Been following this thread and I am still confused on what exactly you are trying to do. Do you want to just back up all files every day that are 10 days old and I assume you will just set this up as a cron job.


----------



## cgjoker (Aug 13, 2003)

the idea is that ill have a file with a numeric flag as part of the filename, that will always be changing. based on this flag i will mv the file if the file is older than that specific flag value. 

so one day the filename may be:

10file.dat

if the file is older than 10 days, move the file.

the next day the filename may be:

7file.dat

if the file is older than 7 days, move the file.

this script would run daily.

so what i was thinking was i could basically say, if a file modification date, plus the flag is less than or equal to the current date then move the file.

to get the flag I was thinking i can just do like a ls into a file then substring (sed) the first 2 characters to get the value of the flag. the problem may be though if there is more than one file... so:

10file1.dat
12filenew.dat
2filewhatever.dat


----------



## cgjoker (Aug 13, 2003)

this is something like the script as id imagine it.. obviously not to code.

date= date command to get this syntax for current date(200509011200)
ls * >> filename.dat
for (each line of file) filename.dat
do
flag= (get 1st 2 characters of filename)
rm line
touch -m -t ${date} ref_file
for file in *
do
if [ $file + $flag -ot ref_file ]
then
mv $ file ./directory/$file
fi 
done
done


----------



## cgjoker (Aug 13, 2003)

i think this may do what i want as well.

ls * >> filename.dat
for (each line in) filename.dat
do
flag= (get 1st 2 char's.)
rm line
for file in `find . -type f -mtime +$flag -name "$flag*.*"` 
do 
mv "$file" /directory/"$file".dat 
done
done


----------



## AGCurry (Jun 15, 2005)

Okay. This solution requires the presence of the "stat" command.

other_directory=/whatever/place
now=$(date '+%s') # Current Unix time in seconds

for file in *
do
daysage=$(echo $file | tr -d [:alpha:][unct:]) #extract number in name
mtime=$(stat -c'%Y' $file) # file's mtime
let seconds_age=$now-$mtime # file age in seconds
let max_seconds=$daysage\*86400 # convert file's max age to seconds
if [ $seconds_age -gt $max_seconds ]
then
mv $file $other_directory
fi
done

I wish indentation was preserved here!


----------



## Squashman (Apr 4, 2003)

AGCurry said:


> I wish indentation was preserved here!


Wrap it in the code tags. [ code ] [ / code ]



AGCurry said:


> Okay. This solution requires the presence of the "stat" command.


I was thinking the same thing when I first read this thread a couple of days ago or using statftime.


----------



## cgjoker (Aug 13, 2003)

excuse my ignorance, but when I attempt to run the code I get an error: 
./file.sh[42]: seconds_age=%s-: 0403-057 Syntax error
./file.sh[41]: stat: not found.

Im using Korne shell, and if I man stat it tells me the entry is not found.

Im also guessing the 
now=$(date '+%s')
it doesn't like.


----------



## cgjoker (Aug 13, 2003)

also, I can figure this out on my own, but I need only the first 2 digits of the filename in case there are other numeric values in the filename.

this should work fine...

echo $file | head -c2

I think ideally though id like the command to get whatever characters are at the beginning of the filename that are numeric... so if I have a filename of 10file.dat the returned value is 10, alternatively, if the filename is 2file.dat, then the returned value is 2.


----------



## AGCurry (Jun 15, 2005)

cgjoker said:


> excuse my ignorance, but when I attempt to run the code I get an error:
> ./file.sh[42]: seconds_age=%s-: 0403-057 Syntax error
> ./file.sh[41]: stat: not found.
> 
> Im using Korne shell, and if I man stat it tells me the entry is not found.


The stat command is found on some systems, but not all. I have it on my Red Hat system here at work, and I've also found it on other systems. It basically makes available any or all elements of the C "struct stat". The ls command is basically a listing of struct stat elements. If you don't have it, it's a pretty simple C program to write. The syntax error above is because stat - because it's not found - returned nothing.

OR... some versions of ls have an option like:

ls -l --time-style='+%s'

which will present the mtime in Unix epoch time.

echo $file | head -c2

will return the first two LINES of $file, not the first two characters. Use

"cut -c1-2" for the first two characters.

so...


```
other_directory=/whatever/place
now=$(date '+%s') # Current Unix time in seconds

ls -g --time-style='+%s' | while read perms links owner size mtime file
do
  if [ -f $file ]
  then
    daysage=$(echo $file | cut -c1-2)     #extract first two chars of name
    if let $daysage=$daysage+0 > /dev/null  # numeric?
    then
      let seconds_age=$now-$mtime          # file age in seconds
      let max_seconds=$daysage\*86400    # convert max age to seconds
      if [ $seconds_age -gt $max_seconds ]
      then
        mv $file $other_directory
      fi
    fi    
fi
done
[\code]
```


----------



## cgjoker (Aug 13, 2003)

nope, no dice...

server1:$:/]ls -l --time-style='+%s'
ls: Not a recognized flag: -
ls: Not a recognized flag: -
ls: Not a recognized flag: y
ls: Not a recognized flag: =
ls: Not a recognized flag: +
ls: Not a recognized flag: %
Usage: ls [-1ACFLNRabcdefgilmnopqrstux] [File...]


----------



## cgjoker (Aug 13, 2003)

could I do something like 
if -mtime +10 <= current time ?


----------



## cgjoker (Aug 13, 2003)

i did this but i get the following error...

for file in *
do 
if [ -f $file ]
then
flag=$(echo $file | cut -c1-2)
#echo "${flag}"
for f in `find . -type f -mtime ${flag} -name "${flag}${file}"`
do 
echo "${flag}"
mv "$f" /directory/"b$f""_$date".dat 
done
fi
done

error:
find: 0652-086 Specify a decimal integer for -mtime
Usage: find Path-list [Expression-list]
find: 0652-086 Specify a decimal integer for -mtime
Usage: find Path-list [Expression-list]
find: 0652-086 Specify a decimal integer for -mtime
Usage: find Path-list [Expression-list]


----------



## cgjoker (Aug 13, 2003)

updated the flag value to make it an expression, now i dont get any errors but the files that are older than the flag and where the name is the same as the flag, are still not moving.

for file in *
do 
if [ -f $file ]
then
flag=`expr $(echo $file | cut -c1-2)`
#echo "${flag}"
for f in `find . -type f -mtime ${flag} -name "${flag}${file}"`
do 
echo "${flag}"
mv "$f" /directory/"b$f""_$date".dat 
done
fi
done


----------



## cgjoker (Aug 13, 2003)

im at a total loss.... it looks like the `find... ` command doesn't recognize predetermined variables. if it did i think this code would work fine...

for file in *
do 
if [ -f $file ]
then
flag=`expr $(echo $file | cut -c1-2)`
echo "${flag}"
for f in `find . -type f -mtime +${flag} -name "${flag}${file}"`
do 
echo "${flag}"
mv "$f" /directory/"b$f""_$date".dat 
done
fi
done


----------



## AGCurry (Jun 15, 2005)

cgjoker said:


> im at a total loss.... it looks like the `find... ` command doesn't recognize predetermined variables. if it did i think this code would work fine...
> 
> for file in *
> do
> ...


Well, your find can't find the file because it's looking for the wrong name.
${flag}${file} - for the file "10farkel.blah" - would be "1010farkel.blah".

find . -name "$file" -mtime +${flag} -exec mv {} /directory \;


----------



## cgjoker (Aug 13, 2003)

I didn't even catch that... thanks. 

Its working great now.. after all that these few lines does just what I need....

for file in `ls *`
do 
flag=`expr $(echo $file | cut -c1-2)`
find . -name "$file" -mtime +${flag} -exec mv {} /directory/"b""$file".dat \;
done

less the removing of the 10 flag but I can do that.

Thanks so much for your help, you guys are great !
c.


----------



## AGCurry (Jun 15, 2005)

Congratulations.

A couple of suggestions:

1. All you need in the first line is "for file in *". No need to load and run ls.

2. The line: flag=`expr $(echo $file | cut -c1-2)` bothers me. One reason is that the expr command should not be needed. The other is that IF there is a file which does not begin with numeric digits, find will fail. A test that $flag is numeric should probably be incorporated, e.g., 

if let $flag=$flag+0
then
find ...

Good luck!
Andy


----------



## cgjoker (Aug 13, 2003)

I see your point about the test, however, if there is a file with non numeric values it would just be ignored and the others would still get processed would it not?

by the way, im trying to add something where if the file has a numeric value it does one thing, if it has a two numerics it does another.. im can't seem to get it.. can you help please?

if ( $file =~ /[^0-9][a-zA-Z]*/ )
then
newfile=`echo $file | cut -b2- | sed -e 's/.dat//g'`
else
newfile=`echo $file | cut -b3- | sed -e 's/.dat//g'`
fi


----------



## AGCurry (Jun 15, 2005)

cgjoker said:


> I see your point about the test, however, if there is a file with non numeric values it would just be ignored and the others would still get processed would it not?
> 
> by the way, im trying to add something where if the file has a numeric value it does one thing, if it has a two numerics it does another.. im can't seem to get it.. can you help please?
> 
> ...


I often find it easiest to use "case" for this kind of thing:

case "$file" in
[0-9][0-9]*) do one thing ;;
[0-9]*) do another thing ;;
*) do something else ;;
esac


----------



## cgjoker (Aug 13, 2003)

thanks again... c.


----------



## cgjoker (Aug 13, 2003)

So im trying to figure out how I can use the case loop for this? So the idea again was that I want to be able to get either files that have 2 digits or 1 digit in the file name.
In the code below, it is only going after 2 digits.

cd /olddirectory

for file in `find . -name "00*.*"`
do	
if [ $file ]
then 
fnow=`echo $file | cut -b4- | sed -e 's/.dat//g'` 
mv "$file" /directory/"$fnow""_$date".dat
done

for ffile in *
do 
if [ $ffile ]
then
fflag=`echo $ffile | cut -c2` 
newffile=`echo $ffile | cut -b3- | sed -e 's/.dat//g'`
find . -name "$ffile" -mtime +${fflag} -exec mv {} /directory/"$newffile""_$date".dat \;

fi


----------



## cgjoker (Aug 13, 2003)

i have an idea ill try and let you know.


----------



## cgjoker (Aug 13, 2003)

my idea didn't work... ill have to rethink this approach...

for fnow in `find . -name "0*.*"`
do	
if [ $fnow ]
then 
case "$fnow" in
[0-9][aA-zZ]*) now=`echo $fnow | cut -b3- | sed -e 's/.dat//g'`;;
[0-9][0-9]*) now=`echo $fnow | cut -b4- | sed -e 's/.dat//g'`;;
*) echo "$dt: no files found, continuing processing" ;;
esac
mv "$fnow" /directory/"b$fnow""_$date".dat

done

for ffile in *
do 
if [ $ffile ]
then
fflag=`echo $ffile | cut -c1-2` 
case "$ffile" in
[0-9][aA-zZ]*) newffile=`echo $ffile | cut -b3- | sed -e 's/.dat//g'`;;
[0-9][0-9]*) newffile=`echo $ffile | cut -b4- | sed -e 's/.dat//g'`;;
*) echo "$dt: no files found, continuing processing" 
;;
esac
find . -name "$fblfile" -mtime +${fflag} -exec mv {} /directory/"b$newfile""_$date".dat \;
echo "$dt: ${ffile} file found equal to 1 
done


----------



## AGCurry (Jun 15, 2005)

cgjoker said:


> my idea didn't work... ill have to rethink this approach...
> 
> for fnow in `find . -name "0*.*"`
> do
> ...


problems:
find command will find files beginning with 0 only.
if [ $fnow ] should be if [ -f $fnow ] ( you want only normal files ).
case is built to recognize file names that find will never find.
cut -b3 - why do you want the 3rd byte? aren't you looking for the first and/or second bytes?


> for ffile in *
> do
> if [ $ffile ]
> then
> ...


Better. But...
if [ $ffile ] doesn't make sense (same reason as above).
fflag=`echo $ffile | cur -c1-2` gets the first two characters. Your case, again, isn't really set up to match the possibilities correctly.

Here's a shot:

for file in *
do
if [ -f $file ]
then
case "$file" in
[0-9][A-z]*) agedays=$(echo $file | cut -c1) ;; # one digit
[0-9][0-9]*) agedays=$(echo $file | cut -c1-2) ;; # two digits
*) agedays=999 ;;
esac

if [ $agedays -ne 999 -a $agedays -gt 0 ]
then
do whatever you need to do
fi
fi
done

case "$file"


----------

