2

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.

2
  • 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, 2009 at 0:27
  • Maybe -> SuperUser? Aug 3, 2009 at 0:59

2 Answers 2

7

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
6
  • Passes my eyeball test.
    – womble
    Aug 2, 2009 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. Aug 2, 2009 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.
    – cas
    Aug 3, 2009 at 1:08
  • 2
    2. use basename to get just the base filename without the dir. eg. 'mv "$OLDEST" /application/inbox/$(basename "$OLDEST").txt'
    – cas
    Aug 3, 2009 at 1:12
  • Good spots, David and Craig. I'll update my answer. Aug 3, 2009 at 4:24
2

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 :-)

1
  • 1
    Ah, neat. I'm not a fan of using the output of ls so it's good to see this solution. Aug 3, 2009 at 4:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .