I've got two directories.

/application/inbox
/application/unresponsive

The application looks for *.txt files in the inbox and works with them. Periodically the application will save entries from these files into date-named (2009-07-31) files in the unresponsive folder.

I'd like to setup a cron job which works once a day to move the oldest file from the unresponsive box into the inbox, adding a *.txt extension so it's picked up by the application.

link|improve this question
I don't believe it will matter what the destination filename is as long as it's a *.txt file and it doesn't overwrite anything else in the inbox, so rather than "adding *.txt" it can generate its' own *.txt filename. Also if I can add the whole thing to the crontab without needing a script file that would be optimal. :) – joebert Aug 3 '09 at 0:27
Maybe -> SuperUser? – Isaac Waller Aug 3 '09 at 0:59
feedback

2 Answers

up vote 7 down vote accepted

Untested, likely buggy:

#!/bin/sh

# last file in list sorted newest->oldest
OLDEST=$(ls -t /application/unresponsive | tail -1)

# make sure $OLDEST isn't empty string
if [ -n $OLDEST ]; then
    # quote in case of spaces and remove directory name
    mv "$OLDEST" /application/inbox/$(basename "$OLDEST").txt
fi
link|improve this answer
Passes my eyeball test. – womble Aug 2 '09 at 21:47
2  
oh so close. $OLDEST will contain /application/unresponsive/2009-07-31, so your mv will try to save the file to /application/inbox//application/unresponsive/2009-07-31.txt, which will no doubt fail. It should be fairly easy to fix using the bash pattern matching operators, but I can never remember which way they go. – David Pashley Aug 2 '09 at 23:03
1  
1. use " characters around every usage of the shell variables - you never know when a file is going to have a space character or something equally annoying in it. – Craig Sanders Aug 3 '09 at 1:08
2  
2. use basename to get just the base filename without the dir. eg. 'mv "$OLDEST" /application/inbox/$(basename "$OLDEST").txt' – Craig Sanders Aug 3 '09 at 1:12
Good spots, David and Craig. I'll update my answer. – markdrayton Aug 3 '09 at 4:24
show 1 more comment
feedback

If you want it to work with files with spaces (more robust). You should loop over them and use the -nt (newest based on modified time) or -ot (oldest) comparison operator with a basic min/max algorithm. Here is an example from this excellent BashFAQ:

files=(*) newest=${f[0]}
for f in "${files[@]}"; do
  if [[ $f -nt $newest ]]; then
    newest=$f
  fi
done

So your example would be (untested):

files=(/application/inbox/*) oldest=${f[0]}
for f in "${files[@]}"; do
  if [[ $f -ot $oldest ]]; then
    oldest=$f
  fi
mv "$oldest" /application/unresponsive/
done

Learning how not to use the output of ls is better I think. Here is link to the argument why. But I leave it up to you to decide if that is true or just pseudo-unix-guru nonsense :-)

link|improve this answer
1  
Ah, neat. I'm not a fan of using the output of ls so it's good to see this solution. – markdrayton Aug 3 '09 at 4:22
feedback

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.