You can define recursive macros that call themselves until some termination is found; a solution to your problem can be as follows:
\makeatletter % we need to use kernel commands
\newcommand{\twoimages}{%
\begin{figure}[!htb]
\@twoimagesi
}
\newcommand\@twoimagesi{\@ifnextchar\stopimages{\@twoimagesend}{\@twoimagesii}}
\newcommand\@twoimagesii[6]{%
\@twoimagesiii{#1}{#2}{#3}\hfill
\@twoimagesiii{#4}{#5}{#6}\\[\bigskipamount]
\@twoimagesi % restart the recursion
}
\newcommand\@twoimagesiii[3]{%
\begin{minipage}{0.49\linewidth}
\centering
\includegraphics[width=#3\linewidth]{#1}
\caption{#2}\label{ris:#1}
\end{minipage}}
\newcommand\@twoimagesend[1]{% The argument is \stopimages
\vspace*{-\bigskipamount}
\end{figure}}
\makeatother
The macro \twoimages really has no argument; it simply starts the business by opening the figure environment and calls the real command, \@twoimagesi. This command checks whether it's followed by \stopimages; if it is, it calls \@twoimagesend that ends the environment; otherwise it executes \@twoimagesii that has the job of printing a row, after having absorbed its six arguments. It does so in an indirect way, so that we can write only once the same minipage, using the first three arguments and the last three.
Then \@twoimagesii restarts the recursion by calling \@twoimagesi again.
Let's see a complete example (I use the demo option to graphicx that draws a black blob instead of requiring external files).
\documentclass{article}
\usepackage[demo]{graphicx}
\makeatletter % we need to use kernel commands
\newcommand{\twoimages}{%
\begin{figure}[!htb]
\@twoimagesi
}
\newcommand\@twoimagesi{\@ifnextchar\stopimages{\@twoimagesend}{\@twoimagesii}}
\newcommand\@twoimagesii[6]{%
\@twoimagesiii{#1}{#2}{#3}\hfill
\@twoimagesiii{#4}{#5}{#6}\\[\bigskipamount]
\@twoimagesi % restart the recursion
}
\newcommand\@twoimagesiii[3]{%
\begin{minipage}{0.49\linewidth}
\centering
\includegraphics[width=#3\linewidth]{#1}
\caption{#2}\label{ris:#1}
\end{minipage}}
\newcommand\@twoimagesend[1]{% The argument is \stopimages
\vspace*{-\bigskipamount}
\end{figure}}
\makeatother
\begin{document}
\twoimages
{a}{Caption left}{.5}
{b}{Caption right}{.5}
{c}{Caption left}{.5}
{d}{Caption right}{.5}
\stopimages
\end{document}

A quite different approach is via the expl3 macros. Also the syntax will be different; I'll present the example, which is almost self-explanatory: the main macro splits its argument at the commas and each chunk is processed in a very similar way as before.
\documentclass{article}
\usepackage[demo]{graphicx}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\twoimages}{ >{ \SplitList {,} } m }
{
\begin{figure}[!htb]
\centering
\ProcessList { #1 } { \davs__twoimages_row:n }
\vspace{-\bigskipamount}
\end{figure}
}
\cs_new_protected:Nn \davs__twoimages_row:n
{
\davs__twoimages_row:nnnnnn #1
}
\cs_new_protected:Nn \davs__twoimages_row:nnnnnn
{
\davs__twoimages_do:nnn { #1 } { #2 } { #3 }
\hfill
\davs__twoimages_do:nnn { #4 } { #5 } { #6 }
\\[\bigskipamount]
}
\cs_new_protected:Nn \davs__twoimages_do:nnn
{
\begin{minipage}{0.49\linewidth}
\centering
\includegraphics[width=#3\linewidth]{#1}
\caption{#2}\label{ris:#1}
\end{minipage}
}
\ExplSyntaxOff
\begin{document}
\twoimages{
{a}{Caption left}{.5}
{b}{Caption right}{.5},
{c}{Caption left}{.5}
{d}{Caption right}{.5}
}
\end{document}
The result is exactly the same as before. There can be any number of sixtuples of arguments, separated by a comma.
Just for completeness, a version that accepts any number of images; now each triple should be separated by a comma; if the number of images is odd, the last one will be centered.
\documentclass{article}
\usepackage[demo]{graphicx}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\twoimages}{ >{ \SplitList {,} } m }
{
\begin{figure}[!htb]
\centering
\leftskip=\fill \rightskip=\fill
\lineskip=\baselineskip % to compensate for the minipages
\ProcessList { #1 } { \__davs_process_argument:n }
\end{figure}
}
\cs_new_protected:Nn \__davs_process_argument:n
{
\__davs_image:nnn #1
}
\cs_new_protected:Nn \__davs_image:nnn
{
\hspace*{\fill}
\begin{minipage}{0.49\linewidth}
\centering
\includegraphics[width=#3\linewidth]{#1}
\caption{#2}\label{ris:#1}
\end{minipage}
\hspace*{\fill}
\penalty0 % we provide a break point
}
\ExplSyntaxOff
\begin{document}
\twoimages{
{a}{Caption left}{.5},
{b}{Caption right}{.5},
{c}{Caption left}{.5},
{d}{Caption right}{.5},
{e}{Caption center}{.5}
}
\end{document}
\images{\image{foo}{bar}{.4}\image{baz}{quux}{.5}...}. – Stephan Lehmke Sep 17 '12 at 14:38numOfParametersarguments to\somecommand1. Am I right when I suppose that it should not be\somecommand1three times but\somecommand1,\somecommand2and\somecommand3? – Ulrich Diez Jul 16 '21 at 15:05