Tenho alguns arquivos com "metacaracteres" no nome, por exemplo, colchetes:
'test[txt].0', 'test[xml].0', 'test[xml].1' | % {New-Item $_} | Out-Null
Posso obter esses arquivos com um glob:
Resolve-Path -Path 'test*'
Path
----
C:\test[txt].0
C:\test[xml].0
C:\test[xml].1
Ou um único deles usando escapes de acento grave:
Resolve-Path -Path 'test`[xml`].0'
Path
----
C:\test[xml].0
Mas não consigo obter aqueles que começam com test[xml].
o uso de escapes de crase e um "curinga":
Resolve-Path -Path 'test`[xml`].*'
Qual seria o correto -Path
a ser utilizado?
Para corresponder arquivos que começam com
test[xml]
o uso de um único glob no PowerShell, você precisa escapar os colchetes corretamente.No PowerShell, o acento grave (`) é usado como caractere de escape. Como você precisa escapar dos colchetes, você deve usar acentos graves duplos para escapar de cada colchete devido a um bug. Espero que eles consertem isso na próxima versão.
Para contornar esse bug, uma possível solução é evitar o uso de qualquer sequência de acento grave-escape; basta colocar o colchete de abertura dentro de colchetes:
observação: aqui não importa se
test[[]xml].*
está sem aspas, entre aspas simples ou duplasPrefácio :
Em casos em que os caminhos devem ser literais , mas que por acaso contêm caracteres
[
e]
, a solução adequada é usar o-LiteralPath
parâmetro em vez do parâmetro (possivelmente implícito na posição )-Path
, conforme discutido nesta resposta ;-LiteralPath
pode ser abreviado-lp
no PowerShell (Core) 7 .No caso em questão, os caminhos são, por padrão, padrões curinga do PowerShell .
Você está vendo um bug de longa data que afeta todos os cmdlets do provedor
Get-ChildItem
(incluindo , por exemplo), relatado pela primeira vez em 2018 no problema #7999 do GitHub , sob o título "Backtick escapando inconsistente" , que captura a essência do problema:Situacionalmente, sem nenhuma razão aparente, você deve escapar duplamente
[
os caracteres e]
para que eles sejam tratados literalmente em vez de metacaracteres curinga , ou seja, como literal``[
e``]
Além disso, às vezes você consegue escapar apenas
[
(não também]
), como no caso em questão (que é como deveria ser, dado que um]
in isolado não é um metacaractere):A variação específica do bug é que o escape duplo inesperadamente se torna necessário devido a escaped
[
(e possivelmente]
) ser combinado com (não escapado)*
ou?
.Em uma nota geral:
Como
`
, o chamado acento grave também serve como caractere de escape em strings expansíveis"..."
(interpoláveis), (ao contrário de strings literais'...'
, ), cada uma`
a ser passada para o comando de destino deve ser duplicada novamente; isso também se aplica a argumentos de palavras simples (argumentos de comando sem aspas), que são implicitamente tratados como strings expansíveis.Portanto, os equivalentes do comando acima são:
Advertência :
Embora a solução alternativa acima e suas variações sintáticas sejam eficazes por enquanto , elas serão interrompidas caso o bug seja corrigido em uma versão futura do PowerShell 7.
Veja a próxima seção para soluções alternativas à prova do futuro .
Soluções alternativas e à prova de futuro , onde o escape funciona conforme o esperado:
Conforme mostrado em sua própria resposta , a solução alternativa mais simples é criar
[
parte de um conjunto de caracteres ([...]
), dentro do qual não é necessário escapar; ou seja, use[[]
:`
o -escaping não está envolvido, isso tem a vantagem adicional de não precisar variar o padrão com base no uso de uma palavra simples'...'
versus aspas."..."
Use a filtragem via
-like
, o operador de correspondência curinga , em uma etapa de pós-processamento viaWhere-Object
; embora menos eficiente, isso funciona de forma previsível:No contexto de
Get-ChildItem
, se os metacaracteres curinga estiverem confinados ao último componente do caminho, você pode expressar esse componente por meio de um-Filter
argumento, em que[
e]
não exigem escape:-Filter
parâmetro geralmente difere dos curingas do próprio PowerShell: além de-Filter
não oferecer suporte a conjuntos de caracteres e intervalos (por exemplo,[abc]
ou[a-c]
) - razão pela qual[
e]
não exigem escape - a correspondência tem peculiaridades herdadas para compatibilidade com versões anteriores - veja esta resposta para mais detalhes.