0

So I want to free up space in my SSD, and then I saw my gigantic folder of OBS recordings. A lot of them, have been remuxed from mkv to mp4. I want to delete the mkv ones, and keep the mp4 ones. At first I thought of doing rm *.mkv, but then I remembered that there are some that have not been remuxed, and thus have remained at being mkv files. And I want to keep those.

So basically, my goal is to delete every mkv file, as long as another file with the exact same name but with a different file extension exists. I also am aware of the fact that the extension is the name on Linux, but considering the fact that in my use case there are only mp4 and mkv files, I suppose we can just count the last three letters. But I'd like a more robust option. I also don't care about subdirectories, as there are none in my use case.

I googled this, and after scrolling down a lot, I found this: Delete files if condition is met

And the answer suggests this:


for file in `find -type f -size +1000000k -name "*.mkv"`; do
  # This would remove the mkv extension
  noext=${file::-4}

Parts of directories

parentdir=echo $file | cut -d'/' -f2 # This would return 'Directories'

if [ -e "./$parentdir/$noext.rar" ]; then rm -f "./$parentdir/$noext.rar" fi done

I stared at this for a while but I genuinely couldn't figure out how to change it for my needs. I know pretty much nothing about bash.

Also, if you want examples (list of files before and after going through the command(s) needed), here you go (I also put a star "*" after each file that should be deleted for your convenience):

Input::

2022-13-64.mp4  (mkv exists, no operation done)
2022-13-64.mkv* (deleted, mp4 exists)
2025-01-35.mp4  (mkv exists, no operation done)
2025-01-35.mkv* (deleted, mp4 exists)
2027-08-12.mp4  (no mkv, no operation done)
2004-06-01.mkv  (is mkv, but no mp4 exists, no operation done)

Expected Output:

2022-13-64.mp4
2025-01-35.mp4
2027-08-12.mp4
2004-06-01.mkv

Also, keeping the mp4 is higher priority than keeping the mkv. For example if two files with the same "name" (as in, everything before mp4 or mkv) existed, but one was an mp4 and the other was an mkv, the mkv would be deleted and the mp4 would be kept. But sometimes, this is not wanted. For example sometimes only an mkv exists, and no mp4 of the same "name". In that case no deletion would be done on that file.

BOplaid
  • 13

1 Answers1

1

This portable snippet of shell code will process files in the current working directory (but not in subdirectories):

for f in ./*.mkv; do
   [ -f "${f%.mkv}.mp4" ] && echo rm "$f"
done

Just in case, the above is a dry run, it only prints what it would do. If this looks fine, remove exactly the string echo to "arm" the snippet, then run the altered version.

The code loops over pathnames resulting from the expansion of the pattern ./*.mkv. Inside the loop $f (which should be properly quoted) expands to the currently processed pathname; ${f%.mkv} expands to the pathname with .mkv removed from the end; ${f%.mkv}.mp4 expands to the pathname with .mkv removed and then .mp4 added (concatenated). [ -f … ] tests if it's an existing regular file and && runs the next command (echo … in this case) if and only if the preceding one (i.e. our test) succeeds.

Note the standard is ./*.mkv does not match dotfiles. In Bash, if you want our snippet to match also dotfiles, invoke shopt -s dotglob beforehand. For completeness: shopt -u dotglob sets the standard behavior.