This article says you can use a % syntax to remove file extensions:

$ s=a/b.mkv
$ echo ${s%.*}

How do you combine the % syntax with the % in xargs to achieve the desired result for a set of lines?

$ cat | xargs -I % echo ffmpeg -i % (INSERT MAGIC HERE)
ffmpeg -i a/b.mkv a/b.mp4
ffmpeg -i c/d.mkv c/d.mp4
  • s=a/b.mkv; echo ffmpeg -i "$s" "${s%.*}.mp4" – Costas Dec 26 '14 at 12:05
  • Can you provide a solution that involves xargs? It needs to stay to accept multiple lines. I updated my initial posting. – forthrin Dec 26 '14 at 12:16
  • There is no need to use xargs at all. while true ; do read -r s ; echo ffmpeg -i "$s" "${s%.*}.mp4" ; done But usually a liitle bit different syntax is used: for s in files_list ; echo ffmpeg -i "$s" "${s%.*}.mp4" ; done – Costas Dec 26 '14 at 12:22
  • Brilliant answer! Thanks! Is there any use for xargs at all, then? – forthrin Dec 26 '14 at 12:29
  • @Costas please don't post answers as comments. If you do, the question will never be marked as answered. – terdon Dec 26 '14 at 12:39

With the comments given I was able to find a short and beautiful solution:

find . -name '*.mkv' | while read f; do echo ffmpeg -i "$f" "${f%.*}.mp4"; done
  • 1
    In the case for is better for f in $(find . -name '*.mkv') ; do echo ffmpeg -i "$f" "${f%.*}.mp4"; done – Costas Dec 26 '14 at 12:54
  • 1
    @Costas why is for better? Unlike the while version of the OP, your for will break on any whitespace. Ideally, of course, you should use find . -name '*.mkv' -print0 | while IFS= read -r -d '' f; do ... ; done which can also deal with backslashes and newlines but at least don't use the for f in $(find ...) which can't even deal with simple spaces! – terdon Dec 26 '14 at 14:15
  • @terdon OK, you catch me. But OP can avoid problem with witespace just use find . -name '*.mkv' -ls – Costas Dec 26 '14 at 14:24
  • Not really @Costas. That is not portable and also requires some tricky parsing to extract the file name. -print0 is portable and easy to parse with while. – terdon Dec 26 '14 at 14:29
  • Yep, any solution that breaks with whitespace or other special characters is no good. So far my own suggestion stands as the best, as I'm not up for learning a new shell. – forthrin Dec 28 '14 at 16:04

Based on the previous answer, you could also use zsh. If this is your shell:

for i in **/*.mkv; echo ffmpeg -i $i $i:r.mp4


zsh -c 'for i in **/*.mkv; echo ffmpeg -i $i $i:r.mp4'

This would avoid problems with whitespace in filenames.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.