Espacios y paréntesis en Windows PATH variable atornilla archivos por lotes

14

Por lo tanto, mi variable de ruta (Sistema- & gt; Configuración avanzada- & gt; Env Vars- & gt; Sistema- & gt; PATH) está configurada para:

C:\Python26\Lib\site-packages\PyQt4\bin;
%SystemRoot%\system32;
%SystemRoot%;
%SystemRoot%\System32\Wbem;
%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;
C:\Python26\;
C:\Python26\Scripts\;
C:\cygwin\bin;
"C:\PathWithSpaces\What_is_this_bullshit";
"C:\PathWithSpaces 1.5\What_is_this_bullshit_1.5";
"C:\PathWithSpaces (2.0)\What_is_this_bullshit_2.0";
"C:\Program Files (x86)\IronPython 2.6";
"C:\Program Files (x86)\Subversion\bin";
"C:\Program Files (x86)\Git\cmd";
"C:\Program Files (x86)\PuTTY";
"C:\Program Files (x86)\Mercurial";
Z:\droid\android-sdk-windows\tools;

Aunque, obviamente, sin las nuevas líneas.

Observe las líneas que contienen PathWithSpaces - el primero no tiene espacios, el segundo tiene un espacio y el tercero tiene un espacio seguido de un paréntesis.

Ahora, note la salida de este archivo por lotes:

C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\>vcvars32.bat
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin>"C:\Program Files (x86
)\Microsoft Visual Studio 9.0\Common7\Tools\vsvars32.bat"
Setting environment for using Microsoft Visual Studio 2008 x86 tools.
\What_is_this_bullshit_2.0";"C:\Program was unexpected at this time.
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin>      set "PATH=C:\Pro
gram Files\Microsoft SDKs\Windows\v6.0A\bin;C:\Python26\Lib\site-packages\PyQt4\
bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\
WindowsPowerShell\v1.0\;C:\Python26\;C:\Python26\Scripts\;C:\cygwin\bin;"C:\Path
WithSpaces\What_is_this_bullshit";"C:\PathWithSpaces 1.5\What_is_this_bullshit_1
.5";"C:\PathWithSpaces (2.0)\What_is_this_bullshit_2.0";"C:\Program Files (x86)\
IronPython 2.6";"C:\Program Files (x86)\Subversion\bin";"C:\Program Files (x86)\
Git\cmd";"C:\Program Files (x86)\PuTTY";"C:\Program Files (x86)\Mercurial";Z:\dr
oid\android-sdk-windows\tools;"

o específicamente la línea:

\What_is_this_bullshit_2.0";"C:\Program was unexpected at this time.

Entonces, ¿qué es esta mierda?

Específicamente:

  • Directorio en ruta que es correctamente escapó con comillas, pero sin espacios = bien
  • Directorio en camino que se escapó correctamente con comillas, y tiene espacios pero no paréntesis = fino
  • Directorio en ruta que es correctamente Se escapó con comillas, y tiene espacios. y tiene un paréntesis = ERROR

¿Que está pasando aqui? ¿Cómo puedo arreglar esto? Probablemente recurriré a un punto de unión para que mis herramientas sigan funcionando como solución alternativa, pero si tiene alguna idea de esto, avíseme :)

Hennes
fuente
Según mi comprensión de los problemas en cuestión, la respuesta anterior es la correcta, y se basa en tener en cuenta que SET es el comando, y PATH es parte de su argumento, cuyo balance es la nueva cadena PATH. Entonces, OMI, no es que esté escasamente documentado, sino que se parece más a un caso de borde oscuro. Acabo de pasar un par de horas en este tema.
David A. Gray

Respuestas:

12

Esto puede suceder si hay paréntesis no escapados en una línea dentro de un "bloque" (que también usa paréntesis para delimitar).

Por lo general, puede solucionarlo activando la expansión demorada y utilizando variables con !var! en lugar de %var%. No hay muchos más consejos que pueda dar sin ver el código.

Joey
fuente
12

Debería o bien no cualquier cita en el MS-Windows PATH Variable ambiental (Comando PATH) o (b) debería haber comillas alrededor de la expresión completa después de la (Comando SET) . Desafortunadamente, esto no está muy bien documentado por MS, aunque sí indican que si se usan comillas, se incluirán en el valor de la variable (Referencia de la línea de comandos de Windows XP) .

$ SET BLAH="blah blah(1)"
$ ECHO %BLAH%
"blah blah(1)"
$ SET BLAH=blah blah(1)
$ ECHO %BLAH%
blah blah(1)

Esto puede causar problemas que son inconsistentes y, por lo tanto, difíciles de diagnosticar. Por ejemplo, si su ruta incluye "C: \ Python27", su máquina dirá que "python 'no se reconoce como un comando interno o externo, un programa operable o un archivo por lotes". Cuando intentas ejecutar python. Sin embargo, algunas bibliotecas mayo Todavía estará disponible.

Tú lo haces no Necesito "escapar" de espacios o paréntesis. Si necesita escapar de caracteres especiales, ponga comillas alrededor de toda la expresión, incluso El nombre de la variable.

SET "PATH=%PATH%;C:\Program Files (x86)\path with special characters"

o puedes usar paréntesis también.

(SET VAR=can't contain ampersand, parentheses, pipe, gt or lt)

Tenga en cuenta, las comillas dobles deben venir en pares.

(SET VAR=illegal characters!@#$%^*_-+={}[]\:;""',./?)
echo %VAR%
illegal characters!@#$%*_-+={}[]\:;""',./?

Sin embargo, es probable que no haya ningún carácter que sea una ruta válida, lo que causaría un problema con el comando SET.

Mark Mikofski
fuente
Muy bien. Me ayudaste mucho. Gracias.
Rego
1
Realmente escribiste MS-DOS cuando te referías a MS-Windows, y tus comandos eran para MS-Windows. El OP preguntó por MS-Windows. Entonces, ¿por qué lo llamas MS-DOS? No lo sé. Incluso sus enlaces dijeron NT (Eso es - Windows. Solía ​​ser 9X y NT, ahora solo es NT). Windows y MS-DOS son dos sistemas operativos diferentes. He visto el símbolo del sistema de Windows llamado anteriormente DOS, pero incluso eso no es tan incorrecto como lo llamaste.
barlop
@barlop, por supuesto que tienes razón. Gracias por las ediciones. Hasta Windows-95, Windows era una aplicación construida sobre DOS. Podría iniciar Windows escribiendo la win comando en DOS. De hecho, antes de Windows-3.1, todo, como Zork y WordStar eran aplicaciones de DOS. Entonces comenzando con Windows-98, no había DOS. Pero creo que algunos usuarios antiguos como yo aún se refieren erróneamente al shell CMD como un shell DOS. Perdón por la confusión, y gracias de nuevo por aclarar la intención de mi respuesta.
Mark Mikofski
1
Tuviste tratar aconsejado (SET PATH=%PATH%;C:\Program Files (x86)\path with special characters)? ¡Está totalmente mal!
JosefZ
2

Microsoft documenta el problema en " Error al ejecutar los scripts de shell de comandos que incluyen paréntesis ".

La solución que sugieren es utilizar la expansión retrasada.

SETLOCAL ENABLEDELAYEDEXPANSION
SET VAR=string containing ( and ) ...
IF "y" == "y" (
    ECHO !VAR! %VAR%
)
ENDLOCAL

Para establecer una ruta en un bloque if, en lugar de usar SET PATH=, probablemente deberías usar el PATH mando.

SET AddToPath=C:\Program Files (x86)\Whatever

SETLOCAL ENABLEDELAYEDEXPANSION
IF "%X%" == "%Y%" (
    ECHO Adding !AddToPath! to path !PATH!
    PATH !AddToPath!;!PATH!
)

Para otras variables, otra solución puede ser usar comillas, pero en general:

SET "MyVar=C:\Program Files (x86)\Whatever"
mivk
fuente
1

Joey en su respuesta dice

Esto puede suceder si hay paréntesis sin escapar en una línea dentro de un   "bloque" (que también utiliza paréntesis para delimitar).

y eso es verdad Si hay paréntesis no escapados, uno debería escapar de ellos. Eso fue lo que hice; Reemplacé

set PATH=some_path;%PATH%

con

set PATH="some_path;%PATH%"

Y esto solucionó el problema.

Piotr Dobrogost
fuente
2
No Deberías usar set "PATH=some_path;%PATH%"
JosefZ
1

He experimentado algo similar. Microsoft explica el problema aquí: http://support.microsoft.com/kb/329308

Básicamente, en lugar de cambiar la variable Ruta a través de Sistema- & gt; Configuración avanzada- & gt; Env Vars- & gt; Sistema- & gt; RUTA, intente

My Computer->Manage->Computer Management (local)-> Properties-> Advanced-> Environment variables-> Settings
phearce
fuente
1

En Windows 8 he encontrado muy poco éxito con cualquiera de estos métodos. Los paréntesis no funcionan, las citas funcionan, pero la "ruta" que se modifica de esta manera no es la ruta que se usa para ubicar los ejecutables, cmd Todavía parece estar usando la ruta del sistema que heredó cuando abrió la ventana.

Ejemplo: después de determinar la arquitectura del procesador, quiero agregar un par de rutas a la variable de entorno PATH. En realidad, incluso solo agregarlos temporalmente funcionaría, ya que solo los necesito mientras se ejecuta un archivo por lotes. Pero eso ni siquiera funciona.

echo %path% muestra el sistema PATH en el momento en que cmd fue lanzado

set path="%path%;%programfiles(x86)%\company\program\subdir" funciona pero ahora %path% contiene todo entre comillas, y si intento ejecutar un programa en un subdirectorio desde otro lugar, falla. Usando paréntesis alrededor de todo en lugar de comillas. No funciona .

Otra cosa que he notado es que el mismo comando funcionará si se ingresa interactivamente en cmd, pero no si se encuentra en un archivo por lotes. Eso es aterrador. ¡Otra rareza más es la pérdida intermitente del último carácter del valor de una variable de entorno! Otra inconsistencia es con los programas de terceros: algunos pueden manejar un %var% como parámetro, otros no lo hacen.

Pete
fuente
1

Tuve grandes problemas para hacer el siguiente trabajo en Win8 hasta que agregué comillas dobles alrededor del valor que estaba configurando para la variable fromFile. Sin eso, cuando fromFile contenía un nombre de archivo con paréntesis, la siguiente línea que intentaba realizar la sustitución de cadenas para generar la variable toFile estaba fallando. Tenga en cuenta que utilizo la expansión demorada allí para evaluar la variable en el tiempo de ejecución en lugar de en el tiempo de análisis (de la instancia CALL respectiva)

::-- BATCH file that creates an *_576_5.* file from an *_640_t.* one (copying it)
::-- Author: George Birbilis (http://zoomicon.com)
::-- Credits: String replacement based on http://www.dostips.com/DtTipsStringManipulation.php

@ECHO OFF

::-- Loop for all files recursively --::

FOR /R %%f in (*_640_t.*) DO CALL :process %%f

ECHO(
PAUSE

GOTO :EOF

::-- Per-file actions --::

:process

:: Display progress...
::ECHO Processing %*
<nul (set/p dummy=.)

SETLOCAL ENABLEDELAYEDEXPANSION
SET fromFile="%*"
SET toFile=!fromFile:_640_t=_576_t!

IF NOT EXIST %toFile% CALL :generate %fromFile% %toFile%

GOTO :EOF

::-- Generate missing file --::

:generate

ECHO(
ECHO COPY %*
COPY %*

::PAUSE

GOTO :EOF
George Birbilis
fuente