Tente algo como o seguinte, em vez no arquivo raiz .htaccess :
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(site1|site2|site3)/?(.*) /$1/public/$2 [L]
Isso segmenta qualquer URL que inicie /site1 , /site2 ou /site3 (observe que em .htaccess o padrão exclui o prefixo de barra). Em seguida, reescreve internamente a solicitação de /site1/<whatever> para /site1/public/<whatever> usando as referências anteriores $1 e $2 . A barra opcional no padrão RewriteRule garante que ela também corresponderá a uma solicitação para o subdiretório bare, excluindo a barra final, por exemplo. /site1 , em vez de permitir que mod_dir emita primeiro um redirecionamento para /site1/ .
Para reescrever qualquer diretório raiz (não apenas limitando a site1 , site2 , etc.), altere a diretiva RewriteRule para ler:
RewriteRule ^([^/]+)/?(.*) /$1/public/$2 [L]
A regex [^/]+ corresponde apenas ao primeiro segmento do caminho, ou seja, tudo excluindo a primeira barra.
A diretiva RewriteCond que verifica a variável de ambiente REDIRECT_STATUS garante que não obtenhamos um loop de regravação. REDIRECT_STATUS não é definido quando o script é chamado pela primeira vez, mas definido para o status HTTP na primeira reescrita (ou estado de erro).
#RewriteRule /(.?)/ /$1/public/ [L]
Alguns problemas com sua diretiva original ...
-
.?captura apenas um único caractere - o que você tornou opcional. -
/(.?)/seria correspondido em qualquer lugar no URL solicitado (não no início). Mas note que você não pode igualar a primeira barra no início do caminho da URL em um contexto de diretório.htaccess/ (como mencionado acima). - Você não está capturando o restante do caminho da URL, portanto, isso só seria reescrito na raiz do documento, independentemente de qual URL foi solicitado.
- Isso acionaria um loop de reescrita. (Resultando em um erro interno do servidor 500.)