¿Cómo se evita la sobrepoblación de la variable de entorno PATH en Windows?

115

Me gustaría saber cuáles son los enfoques que utiliza para administrar los ejecutables en su sistema. Por ejemplo, tengo casi todo accesible a través de la línea de comando, pero ahora llego al límite de la cadena de ruta, por lo que no puedo agregar más dir.

Entonces, ¿qué me recomienda? Hace mucho tiempo, traté de usar softLinks de los ejecutables en un Dir que pertenecía a la ruta, pero ese enfoque no funcionó. Lanzar el "ejecutable solamente" a un Dir conocido, tiene el problema de que casi cualquier aplicación requiere un conjunto de archivos, por lo que esto también es malo. Lanza el ejecutable y todos sus archivos a un Dir conocido, mmm esto funcionará, pero la posibilidad de tener un conflicto en el nombre de los archivos es muy, muy alta. ¿Crear un enlace duro? no lo sé. ¿Qué piensas?

mjsr
fuente
¿Por qué usas tantos caminos? La ruta generalmente se usa para el directorio común, cuando su aplicación debe compartir extender objeto / aplicación / lib con otros. Usar tanto hace que la aplicación comience más lento. ¿Puede dar más detalles sobre cómo usa, crea la ruta del entorno var?
pinichi
1
hola pinichi, bueno, muchas aplicaciones usan el estándar "C: \ Program File \ AppNAme \ ...", y en mi caso, muchas de estas aplicaciones pueden ejecutarse en una línea de comandos o necesitan ser accesibles para otras aplicaciones ( por ejemplo los ejecutables de Miktex que cualquier editor de Tex espera que existan), por lo que deben estar en el PATH. No quiero conocer un enfoque mejor porque el mío es insostenible
mjsr
1
Esta herramienta comprimirá las rutas. El resultado es impresionante: uweraabe.de/Blog/2014/09/09/the-garbled-path-variable/#more-337
InTheNameOfScience

Respuestas:

84

Una forma en la que puedo pensar es usar otras variables de entorno para almacenar rutas parciales; por ejemplo, si tienes

C:\this_is_a\long_path\that_appears\in_multiple_places\subdir1;
C:\this_is_a\long_path\that_appears\in_multiple_places\subdir2;

entonces puedes crear una nueva variable de entorno como

SET P1=C:\this_is_a\long_path\that_appears\in_multiple_places

después de lo cual tus caminos originales se vuelven

%P1%\subdir1;
%P1%\subdir2;

EDITAR: Otra opción es crear un bindirectorio que contenga .batarchivos que apunten a los .exearchivos apropiados .

EDICIÓN 2: El comentario de Ben Voigt a otra respuesta menciona que el uso de otras variables de entorno como se sugiere podría no reducir la longitud de %PATH%porque se expandirían antes de almacenarse. Esto puede ser cierto y no lo he probado. Sin embargo, otra opción es usar formularios 8dot3 para nombres de directorio más largos, por ejemplo, C:\Program Filesnormalmente es equivalente a C:\PROGRA~1. Puede utilizar dir /xpara ver los nombres más cortos.

EDICIÓN 3: Esta simple prueba me lleva a creer que Ben Voigt tiene razón.

set test1=hello
set test2=%test1%hello
set test1=bye
echo %test2%

Al final de esto, verá salida en hellohellolugar de byehello.

EDITAR 4: en caso de que decida usar archivos por lotes para eliminar ciertas rutas %PATH%, es posible que le preocupe cómo pasar argumentos de su archivo por lotes a su ejecutable, de modo que el proceso sea transparente (es decir, no notará ninguna diferencia entre llamar al archivo por lotes y llamar al ejecutable). No tengo mucha experiencia escribiendo archivos por lotes, pero esto parece funcionar bien.

@echo off

rem This batch file points to an executable of the same name
rem that is located in another directory. Specify the directory
rem here:

set actualdir=c:\this_is\an_example_path

rem You do not need to change anything that follows.

set actualfile=%0
set args=%1
:beginloop
if "%1" == "" goto endloop
shift
set args=%args% %1
goto beginloop
:endloop
%actualdir%\%actualfile% %args%

Como regla general, debe tener cuidado al ejecutar archivos por lotes desde Internet, ya que puede hacer todo tipo de cosas con archivos por lotes, como formatear su disco duro. Si no confía en el código anterior (que escribí), puede probarlo reemplazando la línea

%actualdir%\%actualfile% %args%

con

echo %actualdir%\%actualfile% %args%

Idealmente, debería saber exactamente qué hace cada línea antes de ejecutarla.

Mitch Schwartz
fuente
1
el formulario 8dot3 funciona bien, pero para directorios realmente grandes no es demasiado bueno, por ejemplo "C: \ Archivos de programa (x86) \ Microsoft Visual Studio 2008 SDK \ VisualStudioIntegration \ Tools \ Sandcastle \ ProductionTools \". Otra cosa que me ahorró un poco fue que, como usuario, podía crear una variable PATH basada en la ruta del sistema y agregar cualquier otro directorio. Todos estos enfoques son del tipo "compactar esa cadena", pero ¿podemos tener un directorio centralizado de binarios, como lo ha hecho Unix?
mjsr
1
Mmmm, con respecto a directorios muy largos, creo que lo contrario es cierto: cuanto más largo sea el directorio, más caracteres guardarás usando el formato 8dot3. Si es difícil navegar cmd, tenga en cuenta que puede usar *para guardar la escritura. Entonces, por ejemplo, desde la raíz, escriba dir /x pro*. Verá el directorio deseado allí junto con su nombre 8dot3. Luego use cdpara navegar hasta él y repita el proceso.
Mitch Schwartz
1
Con respecto a UNIX, ahí tienes $PATHque funciona de manera muy similar a %PATH%Windows, así que no estoy seguro de cuál es exactamente tu punto. Por convención, los nombres de directorio de UNIX tienden a ser más cortos que en Windows y, como resultado, $PATHtambién tienden a ser más cortos.
Mitch Schwartz
2
Gracias Mitch, ¡la Edición 4 que me proporcionas es lo que quería !, ahora puedo tener una carpeta centralizada con todos los binarios que necesito. Voy a probar más en profundidad para ver si hay un problema con alguna aplicación
mjsr
2
Su sección 'editar 4' es demasiado complicada para pasar argumentos al ejecutable. Vea la respuesta de Michael Burr.
Dave Andersen
83

Esto analizará su variable de entorno% PATH% y convertirá cada directorio a su equivalente de nombre corto y luego lo volverá a unir todo:

@echo off

SET MyPath=%PATH%
echo %MyPath%
echo --

setlocal EnableDelayedExpansion

SET TempPath="%MyPath:;=";"%"
SET var=
FOR %%a IN (%TempPath%) DO (
    IF exist %%~sa (
        SET "var=!var!;%%~sa"
    ) ELSE (
        echo %%a does not exist
    )
)

echo --
echo !var:~1!

Tome la salida y actualice la variable PATH en las variables de entorno.

Todd Smith
fuente
¡¡Gracias eso fue muy útil !! ¡Acortó mi camino de 1990 a 1338 y todo todavía funciona como un encanto! Elegí su enfoque porque quería mantener todo en mi camino y la vinculación de los archivos por lotes habría consumido demasiado tiempo. ¡GRACIAS!
ndrizza
2
Esto también fue útil porque me informó acerca de todos los directorios inexistentes en mi ruta que se habían acumulado con el tiempo.
Nate Glenn
27
Rapid Environment Editor es otra forma de hacer esto. Destaca los directorios que no existen y tiene la opción "convertir ruta larga en corta".
Russell Gallop
3
@RussellGallop: eso, señor, es una herramienta increíble.
elo80ka
1
Tenga en cuenta la cita de cierre que falta después %%~sa. Intenté actualizar la respuesta, pero no me dejará a menos que cambie 6 caracteres
zr870
28

si está utilizando Windows Vista o superior, puede crear un enlace simbólico a la carpeta. por ejemplo:

mklink /d C:\pf "C:\Program Files"

haría un enlace para c:\pf lo que sería su program filescarpeta. Eliminé 300 caracteres de mi camino usando este truco.

bmg002
fuente
Esta es una buena alternativa al uso de una variable de entorno para representar una ruta parcial.
porcus
1
Esto definitivamente ayudaría más, pero si desea una solución más "correcta" (¿compatible?), Puede reemplazar las instancias de c:\Program Filesy c:\Program Files (x86)con las variables predefinidas %ProgramFiles%y %ProgramFiles(x86)% tenforums.com/tutorials/ ... Estos solo guardan unos pocos caracteres cada uno. , pero si REALMENTE estás a punto de maximizar PATH, podría ser la diferencia. De hecho, voy a crear% pf% y% pfx% que se resuelven en las rutas correctas. ¡Gracias por la idea! :)
rainabba
El problema con el uso de variables como% pf% y% pfx% es que tiene los mismos problemas que al crear enlaces simbólicos: las actualizaciones de software pueden agregar cosas nuevamente a la variable de ruta. El otro problema con el uso de variables como esa es que no es rápido y fácil escribir cosas a su alrededor o buscarlas desde el explorador. Usando el método que describí, literalmente puede abrir c: \ PF. Windows lo ve como una carpeta, por lo que también puede escribir bat o powershell contra él con bastante facilidad.
bmg002
10

En caso de que alguien esté interesado ...

Me parece que nunca necesito todas esas rutas a la vez, así que creo un montón de archivos por lotes de "inicialización" que modifican la ruta en consecuencia.

Por ejemplo, si quisiera hacer algún desarrollo de C ++ en Eclipse, haría:

> initmingw
> initeclipse
> eclipse

Esto también es útil para evitar conflictos entre ejecutables con el mismo nombre (como los compiladores C ++ y D, que tienen un make.exe).

Mis archivos por lotes suelen tener este aspecto:

@echo off
set PATH=C:\Path\To\My\Stuff1;%PATH%
set PATH=C:\Path\To\My\Stuff2;%PATH%

Encuentro este enfoque relativamente limpio y aún no he tenido ningún problema con él.

YellPika
fuente
7

Por lo general, no tengo que preocuparme por esto (no me he topado con un límite de tamaño de ruta, ni siquiera sé qué es eso en los sistemas modernos de Windows), pero esto es lo que podría hacer para evitar poner el directorio de un programa en el camino:

  • la mayoría de las utilidades de línea de comando se lanzan a un c:\utildirectorio que está en la ruta
  • de lo contrario, agregaré un archivo cmd / batch simple al c:\utildirectorio que se parece a:

    @"c:\program files\whereever\foo.exe" %*
    

que esencialmente crea un alias para el comando. No es necesariamente perfecto. Algunos programas realmente insisten en estar en el camino (eso es bastante raro hoy en día), y otros programas que intentan invocarlo pueden no encontrarlo correctamente. Pero para la mayoría de los usos funciona bien.

Pero en general, no he tenido que preocuparme por evitar agregar directorios a la ruta.

Michael Burr
fuente
Cuando comience a seguir esta "ruta", tenga en cuenta que un script por lotes no puede llamar a otro script por lotes sin la sintaxis "CALL [bat]". Por lo tanto, si desea asegurarse de que su exe reenviado o no sea llamado desde un bat, use "call php script.php" en lugar de solo "php script.php" (que funciona en ambos sentidos). Una excelente razón para usar. bat dispatcher es para evitar conflictos de nombres PATH (versión múltiple del mismo exe)
131
@ 131: ¿Le importaría explicar lo que quiere decir con 'este "camino"'? ¿Te refieres a la ruta de archivo particular del ejemplo? ¿O más bien el método general sugerido por esta respuesta?
OR Mapper
@ORMapper: cuando 131 dice, 'Cuando comienzas a seguir este "camino"', quiere decir, 'Cuando usas esta técnica'.
Michael Burr
1
Como escribió, "otros programas que intentan invocarlo pueden no encontrarlo correctamente", por ejemplo: Desafortunadamente, puede lanzar llamadas automáticas a aplicaciones de línea de comandos, por ejemplo, mediante herramientas de compilación como NAnt, por supuesto. Un remedio es invocar el comando con un prefijo cmd /c, pero eso a su vez significa que el script de compilación se vuelve específico de Windows: / He preguntado sobre eso en una pregunta separada .
OR Mapper
5

Otra idea: use DIR / X para determinar los nombres cortos generados para los nombres de archivo que no son 8dot3. Luego utilícelos en su% PATH%.

Por ejemplo, 'C: \ Archivos de programa' se convierte en 'C: \ PROGRA ~ 1'.

Eva de Android
fuente
1
Vaya, me acabo de dar cuenta de que esto ya fue sugerido por @Mitch. Le voy a dar un +1 por eso. :)
Android Eve
2

Escribí y uso siempre una secuencia estándar (stdin / stderr / stdout) y el código de salida del programa PROXY (llamado dispatcher https://github.com/131/dispatcher )

Todo el programa CLI que uso (nodo, php, python, git, svn, rsync, plink ...) que estoy usando son en realidad el mismo archivo exe (alrededor de 10kb, que solo nombro de manera diferente), que puse en el mismo directorio. Un archivo de texto claro estático ficticio hace el "nombre de archivo proxy para mapeo exe real".

Dispatcher utiliza la API win32 de gestión de procesos de bajo nivel para ser absolutamente transparente.

Al usar este software, solo tengo UN directorio adicional configurado en mi RUTA para todos los programas que pueda usar.

131
fuente
1

La creación de una carpeta c: \ bin agregando a su ruta y la vinculación dura como dijo podría acortar la cadena. Tal vez agregue una variable pf a las variables del sistema con el valor c: \ Archivos de programa y luego reemplace c: \ Archivos de programa con% pf% en la ruta.

Editar:

Crea una unidad virtual. subst p: "c: \ archivos de programa"

troynt
fuente
1
Creo que la ruta contendría las variables expandidas, en cuyo caso no se acortaría.
Ben Voigt
0

Sigo estos pasos para que las entradas sean manejables:

  1. Creó diferentes usuarios para diferentes combinaciones de uso de paquetes de software. Ejemplo: (a) Creó una web de usuario para poner a disposición todo el software de desarrollo web; (b) Creó una base de datos de usuarios para poner a disposición todos los paquetes de software de base de datos y almacenamiento de datos. Recuerde que algunos programas pueden crear más de una entrada. O en algún momento lo divido en usuarios específicos de Oracle y MSSQL y específicos de Oracle. Puse MySQL / PostgreSQL, tomcat, wamp, xamp en la cuenta de usuario webr.

  2. Si es posible, instale paquetes comunes como office, photoshop, .. como específicos del sistema disponibles para todos los usuarios y paquetes especiales como específicos del usuario. Por supuesto, tuve que iniciar sesión en diferentes usuarios e instalarlos. No todo el software puede ofrecer esta opción. Si la opción "instalar solo para este usuario" no está disponible, instálela para todo el sistema.

  3. Evito instalar programas en la carpeta Archivo de programa (x86) o en Archivo de programa. Siempre lo instalo en el directorio base. Por ejemplo, MySQL de 64 bits va a "C: \ mysql64" y MySQL de 32 bits va a la carpeta "C: \ mysql". Siempre asumo agregar un sufijo 64 solo para software de 64 bits. Si no hay sufijo, entonces es de 32 bits. Sigo lo mismo para Java y otros. De esta manera mi ruta será más corta, sin incluir "C: \ Archivo de programa (x86)". Para algunos software, es posible que sea necesario editar el archivo de configuración para mostrar dónde está exactamente el archivo .exe. Solo el programa que exige ser instalado en "C: \ Archivo de programa (x86)" se instalará en esa carpeta. Siempre recuerdo acortar los nombres. Evito el número de versión como tomcat / release / version-2.5.0.3 tales detalles. Si necesito la versión conocida, Creo un archivo por versión de nombre y lo coloco en la carpeta tomcat. En general, acorte el enlace tanto como sea posible.

  4. Incluya cualquier lote para reemplazar el enlace abreviado a la ruta, si todos los pasos anteriores superaron el límite de Windows.

A continuación, inicie sesión en un usuario específico de uso (aplicación móvil, base de datos / almacenamiento de datos o desarrollo web .. ..) y realice las tareas pertinentes.

También puede crear ventanas virtuales dentro de las ventanas. Siempre que tenga una copia del sistema operativo con licencia, es posible crear varias ventanas virtuales con la misma clave. Puede colocar paquetes específicos para una tarea en particular en esa máquina. Tienes que iniciar una máquina virtual separada cada vez. Algunos paquetes de memoria intensiva, como los creadores de películas de animación en 3D, deben colocarse en la máquina principal, no en la VM, ya que la VM solo tendrá una parte de la RAM disponible para su uso. Sin embargo, es una molestia arrancar cada VM.

Dr. A. Anukanth
fuente
0

Las soluciones anteriores solo funcionan si puede recortar su camino. En mi caso, esa no era realmente una opción, y era una molestia tener que ejecutar un script cada vez que abría un símbolo del sistema. Así que escribí un script simple que se ejecuta automáticamente al abrir el símbolo del sistema y agrega el contenido de un archivo de texto a su ruta.

También hay algunos contextos en los que la ejecución de este script rompe las cosas (por ejemplo, en un shell github o cygwin), por lo que también agregué un archivo que contiene una lista de rutas que, si el símbolo del sistema se inicia en ellas, la variable de ruta no es no cambió a través del script de inicio que normalmente actualiza la ruta.

@echo off

:: Modify these to the actual paths of these two files
set dontSetupFile=C:\Users\Yams\Dontsetup.txt
set pathFile=C:\Users\Yams\Path.txt

:: Retrieve the current path (for determining whether or not we should append to our path)
set curDir=%cd%

:: Be done if the current path is listed in the dontSetupFile
SetLocal EnableDelayedExpansion
for /F "delims=" %%i in (%dontSetupFile%) do (
    if "%%i"=="%curDir%" GOTO AllDone
)



:: Append the pathFile to our current PATH
set pathAppend=
for /F "delims=" %%i in (%pathFile%) do (set pathAppend=!pathAppend!%%i)

set PATH=%PATH%;%pathAppend%


:: The only way to actually modify a command prompt's path via a batch file is by starting
::   up another command prompt window. So we will do this, however, if this script is
::   automatically called on startup of any command prompt window, it will infinately 
::   recurse and bad things will happen.

:: If we already ran, we are done
if "%yams%"=="onion" GOTO AllDone

:: Otherwise, flag that we just ran, and then start up a new command prompt window
::   with this flag set
set yams=onion

cmd \K set PATH=%PATH%;

:: When that command prompt exits, it will load back up this command prompt window, and
::   then the user will need to exit out of this as well. This causes this window to
::   automatically exit once the cmd it just spawned is closed.
exit()

:: Path is set up, we are done!
:AllDone
@echo on

Y Path.txt se verá algo así

C:\Program Files (x86)\Google\google_appengine;
C:\Program Files (x86)\ATI Technologies\ATI.ACE\Core-Static;
C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;
C:\Program Files\Microsoft SQL Server\110\Tools\Binn;
C:\Program Files\Microsoft DNX\Dnvm;
C:\Program Files (x86)\Windows Kits\8.0\Windows Performance Toolkit;

Si bien Dontsetup.txt se verá algo así como

C:\Program Files (x86)\Windows Kits\8.0\Windows Performance Toolkit
C:\Program Files (x86)\Git\cmd
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin

Para que esto se ejecute automáticamente al inicio, abra regedit, navegue hasta HKEY_LOCAL_MACHINE / SOFTWARE / Microsoft / Command Processor, luego haga clic derecho a la derecha y presione nuevo -> Valor de cadena múltiple. Nómbrelo AutoRun. Establezca su valor en

C:\Users\Yams\setUpPath.bat

o en cualquier otro lugar donde almacenó el archivo por lotes anterior.

Phylliida
fuente
0

No lo intenté, pero ¿funcionará dividir PATH en partes y unirlas en la variable final?

Ejemplo inicialmente, digamos que tienes algo como

PATH={LONGPATH1};{LONGPATH2};....{2048th char}....{LONGPATH_N-1};{LONGPATH_N}

En su lugar, crea:

_PATH1 = {LONGPATH1};{LONGPATH2};....{2048 char}
_PATH2 = {2049th char}...{LONGPATH_N-1};{LONGPATH_N}
rem // may be more parts
PATH = %_PATH1%;%_PATH2%
Philipp Munin
fuente