I have some video files in source/ to encode and I want the output to be saved in the local directory, therefore removing source/ in the filename.

I accomplished this by using the following command in fish shell:

$ for file in source/*.mkv
      ffmpeg -i "$file" -c:v copy -c:a copy (echo "$file" | sed -e "s/source\///")

Although, I find piping the output of echo to sed a bit rudimentary, is there a function that just processes the strings of local variables? Like a sed but just for local variables or filenames.


You're removing a (fixed) directory name from the string here.

In standard shell, you can do that with the ${parameter#pattern} expansion, it removes pattern from the start of the string in parameter, so ${file#source/} would remove the prefix source/.

Also in ksh/Bash/zsh ${parameter/pattern} removes the match anywhere in the string, which matches sed's s/pattern// more closely. (${..//..} to remove all matches). Those patterns are the same as the ones used for filename wildcards; they're not regexes.

In fish, there's the builtin string replace command, which seems it can be used here:

> set f source/foobar
> string replace source/ "" -- $f

or with -r for regex, so we don't need to know the path:

> string replace -r "^.*/" "" -- $f

(Note that I'm not that familiar with fish. The above seemed to work, but I'm not sure if it breaks in some corner cases.)


You're looking for basename:

ffmpeg -i $file -c:v copy -c:a copy (basename $file)

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.