1

Here is a simplified version of the powershell script I'm trying to write to join some .mp4 files:

[string]$inputs = ""
$filenames = "input1.mp4", "input2.mp4", "input3.mp4"
foreach ($f in $filenames) {
    $inputs += "-i $f "
}
Write-Host $inputs
.\bin\ffmpeg.exe $inputs -filter_complex...

The write-host prints out the string like I expect, but then ffmpeg gives me an error that says:

Unrecognized option 'i input1.mp4 -i input2.mp4 -i input3.mp4 '. Error splitting the argument list: Option not found

So it looks like when the arguments are being passed to cmd.exe to be passed to ffmpeg, something is getting lost (at least that's how I think it works). I've read other questions that talk about problems with passing double-quotes in arguments, but my problem is with -. Can someone explain what is going in my case? I don't think it's an escaping issue since the second and third - look like they're being passed. Also, if I just use start-process with the -argumentList option (and prepare one big $arguments string beforehand) then everything works.

1
  • 1
    In short: In order to programmatically pass arguments to external programs, construct an array, with each parameter (option) name and parameter value / positional argument (operand) becoming its own element. E.g., to execute foo -o "bar baz", use $a = '-o', 'bar baz'; foo $a. See zett42's answer and the linked duplicate for details. Commented Dec 12, 2022 at 16:41

2 Answers 2

2

When you use PowerShell to call a process like a command (as opposed to using Start-Process), you are not supposed to build up the command-line by low-level string concatenations like you curently do. Instead, pass argument names and values as separate array elements.

PowerShell automatically constructs the final command-line by joining tokens using space character and quotes if necessary.

$filenames = "input1.mp4", "input2.mp4", "input3.mp4"

# $inputs will be an array of strings
$inputs = foreach ($f in $filenames) {
    # Make sure to separate argument names and values.
    # This implicitly adds two elements to the $inputs array.
    '-i', $f
}
Write-Host $inputs

# PowerShell builds up the command-line from the $input array (aka splatting),
# automatically quoting values that contain whitespace.
.\bin\ffmpeg.exe $inputs -filter_complex...

As for what you have tried:

You have build a single string $inputs, that is seen by PowerShell as a single argument to be passed to ffmpeg:

-i input1.mp4 -i input2.mp4 -i input3.mp4

Because the value contains whitespace, PowerShell quotes it so the final command-line looked like this:

.\bin\ffmpeg.exe "-i input1.mp4 -i input2.mp4 -i input3.mp4" -filter_complex...

A quoted string is like a single argument token. So ffmpeg strips the first dash and takes "i input1.mp4 -i input2.mp4 -i input3.mp4" as the argument name.

Sign up to request clarification or add additional context in comments.

Comments

1

I had a look, if you put a space before the '-i' it seems to work, i think this is what you want :)

[string]$inputs = ""
$filenames = "input1.mp4", "input2.mp4", "input3.mp4"
foreach ($f in $filenames) {
    $inputs += " -i $f "
}
Write-Host $inputs
.\bin\ffmpeg.exe $inputs -filter_complex...

2 Comments

No, this won't help, because you fundamentally cannot pass multiple arguments (note that -i and input1.mp4 are separate arguments in the context) via a single string. Use an array instead.
Thanks, this was all that was needed for me.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.