Travis
Travis

Reputation: 669

Extracting end of filename in bash script

Within my backup script, I'd like to only keep 7 days worth of backups (tried using logrotate for this and it worked perfectly, but I ran into issues with the timing of cron.daily and how it affected the "dateext"). I'm running into problems using parameter expansion to extract the date from the filenames.

Here are some examples of some of the files

Here is my bash script:

#!/bin/bash

path="/foo/"
today=$(date +%Y%m%d)
keepDays=7
keepSeconds=$(date -d "-$keepDays day" +%s)

for f in $path"*"; do
  fileSeconds=$(date -d ${f##*-} +%s)
  if [ $fileSeconds -lt $keepSeconds ]
    then
        rm $f
  fi
done

Here is the error I'm getting:

date: extra operand `/foo/foo.bar.tar.gz-20120904'

Upvotes: 0

Views: 209

Answers (2)

Jonathan Leffler
Jonathan Leffler

Reputation: 753455

As cdarke says, remove the quotes around the * in the for loop:

for f in ${path}/*; do

What happens is that the shell executing date gets '/foo/*' and expands that into a list of file names (more than one) and then uses ${f##*-} on part of the list, and date is called with multiple names, and objects.

You'd see this if you ran with bash -x your-script.sh, for instance. When something mysterious goes on, the first step is to make sure you know what the shell is doing. Adding echo "$f" or echo $f in the loop would help you understand — though you'd get two different answers.

Upvotes: 1

cdarke
cdarke

Reputation: 44344

Remove the quotes around the *, that prevents globbing:

for f in ${path}*; do

(the { } are not strictly required here, but make it easier to read)

Not part of the question, but the Bourne shell syntax [ $fileSeconds -lt $keepSeconds ] could be written as (( $fileSeconds < $keepSeconds )) which is possibly safer.

Upvotes: 3

Related Questions