0

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

0

3 Answers 3

2

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
Sign up to request clarification or add additional context in comments.

3 Comments

I haven't read the question thoroughly, but wouldn't: find /my_files/recordings \( -name '*file1.stream*' -mtime +7 -o -name '*file2.stream*' -mtime +1 \) -delete be enough? Also, the _* in the regex is highly useless and the period should be escaped.
Thanks, this was really helpful. I didn't realise I was mixing the two constructs, I had looked at too many different Q&A's and had mixed everything up. I don't need to be checking if the file exists so I have removed it and just gone with regex
Actually I wholeheartedly second @gniourf_gniourf's improvement to only run a single find. It might need a minor change (the *file2.stream placeholder most likely needs to be adapted to the file names you are really working with) but it's much better.
1

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.

Comments

0

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.*$.

1 Comment

Your statement: Don't quote the match string, the quotes will be included in the match and be expected to exist themselves! is just plain wrong.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.