Simon245
Simon245

Reputation: 328

Bash syntax error in for loop

I have a list of files like this "file1.stream_2015-02-17.mp4" that I have been deleting by time using this

#!/bin/bash

CONTENT_DIR=/my_files/recordings
find $CONTENT_DIR -mtime +1 -regextype posix-extended -regex '.*[.](mp4|tmp)$' -delete

That has been working fine for me so far but now I am trying to delete all the ones with file1.stream by 1 day and all the ones with file2.stream by 7 days

I have been trying this but I mainly keep coming up with errors

#!/bin/bash
CONTENT_DIR=/my_files/recordings/*

for f in $CONTENT_DIR; do
  if [[ -f ${f} =~ 'file1.stream_*' ]] then
    find -mtime +7 ${f} -delete
  else
    find -mtime +1 ${f} -delete
  fi
done

but I keep getting this error

syntax error in conditional expression 
syntax error near `=~'
`   if [[ -f ${f} =~ 'file1.stream_*' ]] then'

I am not sure what the error is and I have been looking around for a few hours trying to find the syntax error. Thanks for any help

Upvotes: 0

Views: 137

Answers (3)

mrtimdog
mrtimdog

Reputation: 497

You're trying to do two things at once; check if a file ($f) exists and is a regular file, and attempting to compare the result of that test (which is a return code, not text) with the regex you've given (which also looks like it's using a glob instead of a regex pattern match). Combining the two is also not allowed here. The then is another (built-in) command, you'll need to separate it from the if ... part.

Split the check into the parts it should be, and either use glob matching, or use a regex, eg.:

if [[ -f "${f}" && "${f}" == file1.stream_* ]]; then ...; fi

... or, for regex matching:

if [[ -f "${f}" && "${f}" =~ file1\.stream_.* ]]; then ...; fi

Also note that the regex match does not anchor to the beginning and end and so, unlike the glob match, is effectively the same as ^.*file1\.stream.*$.

Upvotes: 0

tripleee
tripleee

Reputation: 189357

You seem to be contaminating two different constructs. You need to check them both separately.

[[ -f "$f" ]] checks whether the file $f exists and is a regular file.

[[ "$f" =~ regex ]] checks if the string in $f matches the regular expression regex.

You can combine them like this:

if [[ -f "$f" && "$f" =~ regex ]]; then ...

or simply break it up into two separate comparisons:

if [[ -f "$f" ]] && [[ "$f" =~ regex ]]; then ...

Notice also the required semicolon (or newline) before then.

But the pattern you have is a glob pattern, not a regex, so you probably want to use a glob comparison instead.

Additionally, your string is not a valid argument to find -- I suppose you really mean

if ...; then
    find -mtime +7 -name "$f" -delete
: etc

or perhaps (somewhat equivalently, in this context)

if ...; then
    find "$f" -mtime +7 -delete
: etc

where the argument definitely needs to be in double quotes, otherwise the shell will perform wildcard expansion on it and replace the variable with the expanded results, producing yet another syntax error.

Finally, it's not particularly good form to put the pattern in a variable and then use it unquoted. The variable seems to serve no useful purpose, so just inline the pattern into the for loop.

for f in /my_files/recordings/*; do
  if [[ -f "$f" && "$f" == 'file1.stream_'* ]]; then
    find -mtime +7 -name "$f" -delete
  else
    find -mtime +1 -name "$f" -delete
  fi
done

... or even just decide the mtime parameter inside the conditional.

for f in /my_files/recordings/*; do
  if [[ -f "$f" && "$f" == 'file1.stream_'* ]]; then
    mtime=+7
  else
    mtime=+1
  fi
  find -mtime "$mtime" -name "$f" -delete
done

Upvotes: 2

anubhava
anubhava

Reputation: 785058

You have syntax error in your if condition and =~ is used for regex only.

You can use:

#!/bin/bash

for f in /my_files/recordings/*; do
  if [[ -f "$f" && "$f" == 'file1.stream_'* ]]; then
    find "$f" -mtime +7 -delete
  else
    find "$f" -mtime +1 -delete
  fi
done

Also glob pattern needs to be outside quote as shown in my answer above.

Upvotes: 1

Related Questions