Questão Expansão da variável de ambiente em lote quando a variável termina com uma barra invertida?


Eu só preciso perguntar se isso é um comportamento esperado, com certeza me surpreendeu.

Temos um arquivo em lotes que copia alguns arquivos de um subdiretório de onde ele está localizado para outro local em todas as máquinas dos desenvolvedores. Como para alguns desenvolvedores, esse diretório de destino é diferente do restante, definimos uma variável de ambiente do usuário e usamos isso no arquivo em lote.

Esta é uma linha de amostra do arquivo de lote:

ROBOCOPY Staging\*.* "%DISTRIBUTE_TARGET%" *.* /IS

Isso falhou em uma máquina, e depois de alguma experimentação, fiquei sabendo que nessa máquina, a variável tinha uma barra invertida como parte do conteúdo variável.

Na maioria das máquinas (na verdade, todas as outras máquinas, onde funcionava), a variável era assim:

DISTRIBUTE_TARGET=C:\Some\Directory

mas nesta máquina, foi:

DISTRIBUTE_TARGET=C:\Some\Directory\

observe a barra invertida adicionada lá.

A mensagem de erro dada por ROBOCOPY era de que havia algo errado com o segundo parâmetro, mas parecia pensar que tudo, desde o início dessa variável até o final da linha, estava no segundo parâmetro.

Ie. a mensagem de erro ficou assim:

Error in second parameter: "C:\Some\Directory\" *.* /IS"

O que eu suponho que aconteceu é que a barra invertida "escapou" do caractere de citação, que removeu seu significado como "fim do parâmetro citado" e, assim, o resto da linha foi apenas capturado como parte do argumento.

Esse comportamento é esperado? Isso significa que variáveis ​​com barra invertida, por qualquer motivo ou finalidade, simplesmente não podem ser usadas com segurança?


2


origem




Respostas:


Deste artigo:

Se a origem ou o destino   são um "nome dobrado longo" não   incluir uma barra invertida à direita como este   será tratado como um escape   caractere, ou seja, "C: \ algum caminho \"   falhar, mas "C: \ algum caminho \\" ou "C: \ algum   caminho "vai funcionar.

Este é um problema específico para o robocopy. Eu chegaria a ponto de chamá-lo de um bug.

Você não tem outra solução a não ser adicionar código ao seu arquivo de lote que verificará e excluirá uma barra invertida do final da origem e do destino.


2



Errado. Este é um bug-vendido-como-recurso na expansão da variável shell do Windows. Por que isso é marcado como resposta? - Daniel Dinnyes
@DanielDinnyes: Minha explicação acima está correta, já que a análise da linha de comando é feita por robocopy e não pelo Windows. O Windows usa a barra invertida como o separador de diretório e não possui um caractere de escape. A rotina de análise de robocopy foi provavelmente retirada do Linux e vê um caractere de escape onde não existe nenhum, então trata o \"Como " que está incluído na string. Então continua a string até o próximo ", fica confuso e gera um erro. - harrymc
Como o acima foi escrito em 2010, esse problema pode ainda não existir hoje em robocopy. - harrymc
Sua explicação não está correta. A resposta correta está abaixo do @Kevin. Isso não tem nada a ver com robocopy. O shell script que o OP escreveu tem o problema, já que o robocopy recebe "C:\Some\Directory\" *.* /IS" como segundo argumento do shell. Não é o erro no robocopy que a segunda string não é reconhecida como um caminho válido. - Daniel Dinnyes
@harrymc, minhas desculpas, estou atrasado alguns meses com a minha resposta. :) Mas mesmo assim ... Não tente com o dir comando, como não é um executável. Tente iniciar um arquivo * .exe, passando alguns argumentos em que o primeiro é como "c: \ folder \". O Windows estraga isso quando está passando os argumentos para o novo processo ... - elgonzo


Na verdade, isso não é específico para robocopy, mas sim o CommandLineToArgvW Função da API do Windows.

CommandLineToArgvW tem uma interpretação especial de caracteres de barra invertida quando eles são seguidos por um caractere de aspas ("), da seguinte maneira:

2n barras invertidas seguidas por aspas produzem n barras invertidas seguidas por uma aspa.

(2n) + 1 barras invertidas seguidas por uma aspa novamente produzem n barras invertidas seguidas por uma aspa.

n barras invertidas não seguidas por aspas simplesmente produzem n barras invertidas.

As mesmas regras são descritas em Analisando Argumentos de Linha de Comando do C ++

Uma solução alternativa é anexar . para tudo que você conhece é um diretório (por exemplo, "C:\Program Files\.")


5



Eu adicionaria \. até o fim. Tem o mesmo efeito, mas é menos confuso, portanto propenso a erros. Tendo uma . no final do nome do diretório é removido durante a navegação e as operações do sistema de arquivos, mas pode causar problemas se algum programa para o qual você passa tentar fazer algo com ele sem estar ciente da remoção de pontos feita pelo Windows. Essa coisa é misteriosa! - Daniel Dinnyes
Seja cuidadoso: \. não é o mesmo que \\.. (Este último é interpretado como um caminho UNC inválido) - Kevin Smyth