Archive won't move

I' writing a script trying to archive the oldest two directories from one place, tar them, and move them to another.

#!/bin/bash

cd (/dir/with/dirforarchiving)
ARCHIVE=(/temp/dir/)
FIND=$(find . -maxdepth 1 -type d)
ARRAY=(`ls ${FIND} -ltd | tail -2`)

names=(${ARRAY[7]} ${ARRAY[15]})
dates=(${ARRAY[5]} ${ARRAY[13]})

for i in {0..1}
do
        CUT=$(echo ${dates[$i]} | cut -d- -f1,2)
        if [[ -d ${ARCHIVE}${CUT[$i]} ]]
        then
                tar -zcvf ${names[$i]}.tar.gz ${names[$i]}
                mv ${names[$i]}.tar.gz ${ARCHIVE}${CUT[$i]}
        else
                mkdir ${ARCHIVE}${CUT[$i]}
        fi
done

The problem I'm running into is that the oldest two directories, and some others, were created the same month, date, and different only because their modification time was one or two minutes apart. The oldest two have dates of 2012-07-25, when I run the directory exists check, it will created the directory 2012-07 and move ONE of the two targeted directories into it, the other tar does not go in the target directory but one level up. I want it in /temp/dir/2012-07 one of them goes into that and the other goes to /temp/dir.

How can I fix this?

I cannot figure out what is in those arrays. Parsing ls into an array, and find into a string variable, is very likely to eventually break. It is best to operate using NUL delimited filenames printed from find. We can also have it print the date.

destprefix=/tmp/tars
find . -maxdepth 1 -type d -printf '%Ts %TY-%Tm %f\0' | sort -znk1 | while read -rd '' epoch date dir && ((max++ < 2))
do
    dest=$destprefix/$date
    echo mkdir -p "$dest"
    echo tar -zcvf "$dest/$dir.tar.gz" "$dir"
done

remove the echos if it prints what seems correct

If the archive destination doesn't exist, the else-block creates it but doesn't tar anything. The loop moves on to the second directory, and retests for the archive destination's existence. This time it's there and that second directory is archived.

Disentangle the directory creation from the tarring. In pseudocode, instead of ...

if directory exists
    tar
    mv
else
    mkdir
fi

... try ...

if directory doesn't exist
    mkdir
fi
tar
mv

Regards,
Alister

Thanks neutronscott it worked, can you explain in a little more detail what your code does though? I am unfamiliar with printf, this section was hardest to read.

I understand it for the most part, I'm guessing the...

%TY-%Tm

are the year and month, and that the...

sort -znk1

is sorting in modified date order? Is the...

read -rd

taking the input from the printf?

This helped a lot but I still do not understand why one tar was going into the created directory and the other was not with my script. I tried Alister's script and understand his change, but it yielded me the same result. Both tar files were still not going into the destination directory, only one was even though they should both have been in the same directory.

It's in the find manual. Rather than just printing file names, we include the modify time in epoch and also YYYY-MM format, then finally the filename NUL terminated. So even a filename with a new-line won't mess it up.

-z is to print it back NUL terminated (GNU extention). -nk1 is for numerical sort on first position... bash's read you can set the delimiter to be different than newline. here we set it to '' (empty string, NUL). Yes, it reads off what is piped in from find's -printf for further processing in the shell's while loop.

If alister's suggestion did not fix your script, i'd try bash -x ./script to see exactly what it is doing to follow the logic. It was my first thought.