tags:

views:

49

answers:

4

I have folders with the naming convention:

yearmonthday_jobcode_descriptor

ie 20101007_GR1234_Whatsit

I'm attempting to write a script that does a few things:

  • move any folders where the date is older than $X into ./old
  • move any folders where the date is in the future ./old
  • move any folders that dont conform to the convention ./old
  • delete any folders in ./old where the date is older than $X + $Y

Here is my current loop, as you can see my bash scripting is pretty mediocre.

#!/bin/bash

for file in $1/*; do
   if [ -d $file ]; then
        echo $(echo $file | grep -oE "[0-9]{8}_[A-Z]*[0-9]*_?.*")
   fi
done

I can handle all the looping, my main concern at the moment is how to extract the folder names into variables that can be compared for dates. The current regex above just checks for conformity to the convention.

+2  A: 
$ foo="20101007_GR1234_Whatsit"
$ echo ${foo%%_*}
20101007
Ignacio Vazquez-Abrams
+3  A: 

You can use the cut command to tokenize the string (-d specifies the delimiter, -f specifies which field you want to keep) -

echo 20101007_GR1234_Whatsit | cut -d'_' -f1

gives

20101007

From there, you can use the date command to parse the date-

foo=`date -d 20101007 +%s`

will convert the date string to the epoch time (seconds since Jan 1, 1970) which can then be easily compared.

If you don't want to mess with epoch time, you can call date multiple times to parse the different parts -

 day=`date -d 20101007 +%d`
 month=`date -d 20101007 +%m`
 year=`date -d 20101007 +%Y`

but it will make your comparisons a little more complicated.

Bill B
Thanks, this was the answer i found most useful. Upvoting this and marking my final solution as the answer.
devians
+1 For describing the cut command
Elpezmuerto
A: 
#!/bin/bash


ls -d ????????_[A-Z][A-Z]*_* | awk 'BEGIN{
  x=mktime("2010 10 08 00 00 00") # set your X here, whatever it is
  y=mktime("2010 10 02 00 00 00") # set your Y here, whatever it is
  olddir="/tmp/old"
}
{
   yr=substr($0,1,4) # get year
   mth=substr($0,5,2) # get month
   day=substr($0,7,2) # get day
   t= mktime(yr" "mth" "day" 00 00 00")  #convert to secs for comparison
   if (t < 0) { print "Wrong format: "$0 ;next}
   if ( t > x){
      print $0 " is later than X: "x
   }else{
      print "moving "$0" to old"
      cmd="mv $0 "oldir
      print cmd
      #system(cmd) #uncomment to do actual moving
   }
   if ( t> (x+y) ){
        ..............
   }
}'
ghostdog74
+1  A: 

This was my final solution, for anyone attempting to do this in the future:

#!/bin/bash

ARCHIVE="old"
NOW=`date +%s`
GRACE_PERIOD=$((60*60*24*7*2))
CUTOFF=$(($NOW-$GRACE_PERIOD))
DEADLINE=$(($CUTOFF-$GRACE_PERIOD))

function getos {
    UNAME=`uname`
    PLATFORM="unknown"

    if [[ "$UNAME" == 'Linux' ]]; then
        echo 'linux'
    elif [[ "$UNAME" == 'Darwin' ]]; then
        echo 'osx'
    else
        echo 'linux'
    fi
}

function dateToTimestamp {
    DATE="$1"
    OS=`getos`
    TIMESTAMP='empty'

    if [[ "$OS" == 'linux' ]]; then
        TIMESTAMP=`date -d $DATE +%s`
    elif [[ "$OS" == 'osx' ]]; then
        TIMESTAMP=`date -j -f "%Y%m%d" "$DATE" "+%s"`
    fi

    echo $TIMESTAMP
}

function movetoarchive {
    ITEM="$1"
    if [ ! -d "$ARCHIVE" ]; then
        mkdir $ARCHIVE
    fi

    FOLDER=`date +"%Y%m%d"`

    if [ ! -d "$ARCHIVE/$FOLDER" ]; then
        mkdir $ARCHIVE/$FOLDER
    fi

    mv $ITEM $ARCHIVE/$FOLDER/$ITEM
}

function deletefromarchive {
    ITEM="$1"
    WD=`pwd`

    MATCH=$(echo $WD | grep -oE ".*?/$WORKING_DIR/$ARCHIVE$")
    if [ -n "$MATCH" ]; then
        rm -rf $ITEM;
    fi
}

WORKING_DIR="$1";

cd "$WORKING_DIR"

for file in *; do
    if [ -d $file ]; then
        if [ "$file" != "$ARCHIVE" ]; then
            MATCH=$(echo $file | grep -oE "[0-9]{8}-[A-Z]*[0-9]*-?.*")
            if [ -z "$MATCH" ]; then
                movetoarchive $file
            else
                DATE=$(echo $file | cut -d'-' -f1);
                TIMESTAMP=`dateToTimestamp $DATE`
                if [[ "$TIMESTAMP" > "$NOW" ]]; then
                    movetoarchive $file
                elif [[ "$TIMESTAMP" < "$CUTOFF" ]]; then
                    movetoarchive $file
                fi
            fi
        fi
       fi
done

cd $ARCHIVE

for file in *; do
    if [ -d $file ]; then
        MATCH=$(echo $file | grep -oE "^[0-9]{8}$")
        if [ -z "$MATCH" ]; then
            deletefromarchive $file
        else
            TIMESTAMP=`dateToTimestamp $file`
            if [[ "$TIMESTAMP" > "$NOW" ]]; then
                deletefromarchive $file
            elif [[ "$TIMESTAMP" < "$DEADLINE" ]]; then
                deletefromarchive $file
            fi
        fi
    fi
done
devians