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.

2 Answers 2


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)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .