Acho que o seguinte regexp Perl corresponde ao que você deseja:
(?!.*msg-[-0-9]{4,16}\.html?$).*\.html?$
No entanto AFAIK não existe nenhum lugar onde o bash suporte regexps Perl. O operador =~
suporta apenas regexps estendidos¹, que não incluem asserções lookahead de largura zero, como (?=…)
e (?!…)
.
É teoricamente possível converter um regexp com asserções lookahaed para um sem, mas o regexp resultante seria enorme. É muito mais simples usar dois regexps:
[[ $string =~ \.html?$ && ! $string =~ msg-[-0-9]{4,16}\.html?$ ]]
¹ Primeiro, houve basic regexps (BRE) (com diversas variantes de sintaxe), depois veio extended regexps (ERE) com mais recursos (e novamente diversas variantes de sintaxe). O Perl adicionou ainda mais recursos, e muitos idiomas fornecem expressões regulares compatíveis com Perl (pcre). Mas a bash adere a ERE.