Search code examples
bashfile-managementfile-manipulation

How can I delete a file that doesn't have a matching file with a different extension


It's a bit hard to expliain, but I'm looking for a relatively easy bash script that can delete a file if it doesn't find a file of the same name that is an mp4.

Essentially I have files like:

S01E02 - Name of Episode 2.description
S01E02 - Name of Episode 2.srt
S01E02 - Name of Episode 2.mp4    
S01E03 - Name of Episode 3.description
S01E03 - Name of Episode 3.srt
S01E03 - Name of Episode 3.mp4
S01E04 - Name of Episode 4.description
S01E04 - Name of Episode 4.srt

What I'm trying to accomplish would be to get a bash script setup that can search the files and delete files such as:

S01E04 - Name of Episode 4.description
S01E04 - Name of Episode 4.srt

because there is no matching mp4 file

I only started fooling around with bash a week or so ago so I'm sure it's far easier than I'm making it out to be, but I just can't figure it out myself.


I was thinking of using a for command, but I can't wrap my head around how to identify if the file being looked at has a match or not. I honestly haven't tried much because I can't even think of where to start.

Thanks in advance!


Solution

  • for file in *; do
      [[ $file = *.mp4 ]] && continue  # skip .mp4 files
      mp4_file=${file%.*}.mp4
      [[ -s $mp4_file ]] || rm -f -- "$file"
    done
    

    Let's look at how this works:

    • ${file%.*} is a parameter expansion which strips the shortest string matching .* from the end of the variable file. mp4_file thus has the extension-less name, with .mp4 appended.
    • test -s "$mp4_file", or its modern-bash-syntax alternative [[ -s $mp4_file ]], looks at whether a file thus-named exists and is not empty.
    • foo || bar executes bar if and only if foo returns a boolean-false value.

    Thus, the effect is to loop over files in the current directory, skipping ones that end in .mp4, look for paired or matching .mp4 files, and delete files for which no matching .mp4 is found.