在Windows中如何避免过度填充PATH环境变量?


115

我想知道您用来管理系统中可执行文件的方法是什么。例如,我几乎可以通过命令行访问所有内容,但是现在我达到了路径字符串的限制,因此我无法再添加任何目录。

那么您有什么建议呢?很久以前,我尝试在目录中使用Dir中可执行文件的软链接,但是这种方法不起作用。将“仅可执行文件”扔给已知的Dir,存在几乎所有应用程序都需要一组文件的问题,因此这也是不好的。将可执行文件和他的所有文件扔到一个已知的Dir,mmm,这可以工作,但是文件名冲突的可能性非常高。创建HardLink?我不知道。你怎么看?


为什么要使用这么多路径?当您的应用必须与其他人共享扩展对象/应用/库时,路径通常用于公共目录。大量使用会使应用启动速度变慢。您能否提供有关如何使用,创建路径环境var的更多详细信息?
pinichi 2010年

1
嗨,pinichi,很多应用程序都使用标准的“ C:\ Program File \ AppNAme \ ...”,在我的情况下,很多此类应用程序都可以以命令行方式运行,或者需要其他应用程序可以访问(例如,任何Tex编辑器都希望存在的Miktex可执行文件),因此它们必须位于PATH中。我不会知道更好的方法,因为我的方法不可持续
mjsr 2010年

1
该工具将压缩路径。结果令人印象深刻:uweraabe.de/Blog/2014/09/09/the-garbled-path-variable/#more-337
InTheNameOfScience 2015年

Answers:


84

我可以想到的一种方法是使用其他环境变量来存储部分路径。例如,如果您有

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

然后您可以创建一个新的环境变量,例如

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

之后,您的原始路径变为

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

编辑:另一个选项是创建一个bin目录,该目录包含.bat指向相应.exe文件的文件。

编辑2: Ben Voigt对另一个答案的评论提到使用建议的其他环境变量可能不会减少长度,%PATH%因为在存储之前会先对它们进行扩展。这可能是正确的,但我尚未对此进行测试。不过,另一种选择是将8dot3形式用于较长的目录名,例如C:\Program Files,通常等效于C:\PROGRA~1。您可以dir /x用来查看简称。

编辑3:这个简单的测试使我相信Ben Voigt是正确的。

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

最后,您看到的是输出hellohello而不是byehello

编辑4:如果您决定使用批处理文件消除的某些路径%PATH%,则可能会担心如何将参数从批处理文件传递到可执行文件,以使过程透明(即,您不会注意到任何区别)在调用批处理文件和调用可执行文件之间)。我没有很多编写批处理文件的经验,但这似乎很好。

@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%

通常,您应该谨慎地从Internet运行批处理文件,因为您可以使用批处理文件执行各种操作,例如格式化硬盘。如果您不信任上面的代码(我写过),则可以通过替换以下行来对其进行测试

%actualdir%\%actualfile% %args%

echo %actualdir%\%actualfile% %args%

理想情况下,在运行之前,您应该确切知道每一行的功能。


1
8dot3格式的效果很好,但是对于较大的目录来说并不太好,例如“ C:\ Program Files(x86)\ Microsoft Visual Studio 2008 SDK \ VisualStudioIntegration \ Tools \ Sandcastle \ ProductionTools \”。节省一点的另一件事是,作为用户,我可以在系统路径的基础上创建PATH变量,并添加任何其他目录。所有这些方法的类型都是“压缩字符串”,但是像Unix一样,我们可以拥有一个集中的二进制目录吗?
mjsr 2010年

1
嗯,关于很长的目录,我想相反的是:目录越长,使用8dot3格式保存的字符越多。如果难以导航cmd,请注意,您可以*用来保存输入内容。因此,例如,从根目录输入dir /x pro*。您将在其中看到所需的目录及其8dot3名称。然后使用cd导航到它并重复该过程。
米奇·施瓦兹

1
关于UNIX,那里的$PATH工作原理与%PATH%Windows 十分相似,因此我不确定您的意思是什么。按照惯例,UNIX目录名通常比Windows中的短,因此结果$PATH也往往更短。
米奇·施瓦兹

2
感谢Mitch,您所提供的Edit 4是我想要的!,现在我可以使用所有需要的二进制文件来存放集中的文件夹了。我将进行更深入的测试以查看某些应用程序是否存在问题
mjsr 2010年

2
对于将参数传递给可执行文件的“ edit 4”部分过于复杂。请参阅迈克尔·伯(Michael Burr)的答案。
Dave Andersen

83

这将解析您的%PATH%环境变量,并将每个目录转换为等效的短名称,然后将它们拼凑在一起:

@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!

取得输出并更新环境变量中的PATH变量。


谢谢你,这非常有用!从1990年到1338年,这把我的道路缩短了,一切仍然像魅力!我选择了您的方法,因为我想将所有内容保留在我的路径中,而通过批处理文件进行链接将非常耗时。谢谢!
ndrizza 2014年

2
这也很有用,因为它告诉了我路径中所有不存在的目录,这些目录随着时间​​的推移而累积。
Nate Glenn 2014年

27
快速环境编辑器是执行此操作的另一种方法。它突出显示了不存在的目录,并具有“将长路径转换为短路径”选项。
罗素·盖洛普

3
@RussellGallop:先生,这是一个了不起的工具。
elo80ka 2014年

1
请注意后面缺少的结束语%%~sa。我尝试更新答案,但除非我更改6个字符,否则它不会让我
zr870

28

如果您使用的是Windows Vista或更高版本,则可以建立指向该文件夹的符号链接。例如:

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

会链接,所以c:\pf您的program files文件夹也将链接。通过使用此技巧,我从路径中删除了300个字符。


这是使用环境变量表示部分路径的不错选择。
porcus 2016年

1
这肯定会有更多帮助,但是如果您需要更“正确”的(受支持的?)解决方案,则可以使用,c:\Program Files和的实例替换 c:\Program Files (x86)为预定义的变量%ProgramFiles%%ProgramFiles(x86)% tenforums.com/tutorials/…,每个实例仅保存几个字符。 ,但是如果您真的要最大化PATH的边缘,那就可能有所不同。为此,我将创建%pf%和%pfx%解析为正确的路径。谢谢你的主意!:)
rainabba

使用%pf%和%pfx%之类的变量的问题是,您会遇到与创建符号链接相同的问题-软件更新可能会再次向path变量添加内容。使用这样的变量的另一个问题是,围绕它编写脚本或从资源管理器浏览它们并不方便快捷。使用我描述的方法,您可以从字面上打开c:\ PF。Windows认为它就像一个文件夹,因此您也可以轻松地针对它编写bat或powershell。
bmg002

10

如果有人有兴趣...

我发现我从来没有真正需要过所有这些路径,因此我创建了一堆“初始化”批处理文件,它们会相应地修改路径。

例如,如果我想在Eclipse中进行一些C ++开发,则可以这样做:

> initmingw
> initeclipse
> eclipse

这对于避免具有相同名称的可执行文件之间的冲突也很方便(例如C ++和D编译器都具有make.exe)。

我的批处理文件通常如下所示:

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

我发现这种方法比较干净,并且尚未遇到任何问题。


7

我通常不必为此担心(我还没有遇到路径大小限制-我什至不知道现代Windows系统上的路径大小),但是我可以这样做以避免将程序的目录放在其中路径:

  • 大多数命令行实用程序都被扔到c:\util路径上的目录中
  • 否则,我将向目录中添加一个简单的cmd / batch文件,c:\util如下所示:

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

本质上为命令创建了别名。不一定完美。有些程序确实坚持要走这条路(在当今,这种情况很少见),而其他尝试调用它的程序可能找不到正确的路径。但对于大多数用途来说,它的效果很好。

但是总的来说,我不必担心避免在目录中添加目录。


当您开始遵循此“路径”时,请注意,如果没有“ CALL [bat]”语法,一个批处理脚本将无法调用另一个批处理脚本。因此,如果您想确保从蝙蝠中调用了您的转发或非执行exe文件,请使用“ call php script.php”而不是“ php script.php”(这两种方法均有效),这是一个极好的使用理由。 bat调度程序是为了防止PATH名称冲突(同一exe的多个版本)
131年

@ 131:您介意解释“此“路径””的含义吗?您是指示例中的特定文件路径吗?还是这个答案建议的一般方法?
或Mapper

@ORMapper:当131说“当您开始遵循此“路径”时”,他的意思是“当您使用此技术时”。
迈克尔·伯

1
如您所写,“其他尝试调用它的程序可能无法正确找到它”-恰当的例子:不幸的是,它可能会自动抛出对命令行应用程序的调用,例如通过NAnt之类的构建工具。一种补救措施是在命令前添加命令cmd /c,但这反过来意味着构建脚本将变得特定于Windows:/我在另一个问题中对此进行了询问
OR Mapper

5

另一个想法:使用DIR / X来确定为非8dot3文件名生成的简称。然后在您的%PATH%中使用它们。

例如,“ C:\ Program Files”变为“ C:\ PROGRA〜1”。


1
糟糕,我刚刚意识到@Mitch已经建议了这一点。为此,我要给他+1。:)
Android前夕


2

我经常编写并使用标准流(stdin / stderr / stdout)和退出代码PROXY程序(称为dispatcher https://github.com/131/dispatcher

我正在使用的所有CLI程序(节点,php,python,git,svn,rsync,plink ...)实际上都是相同的exe文件(大约10kb,我只是用不同的名字命名),我将其放在同一目录。虚拟静态明文文件执行“代理文件名到真实exe的映射”。

调度程序使用底层流程管理win32 API绝对透明。

使用此软件,我在PATH中仅为我可能使用的所有程序设置了一个附加目录。


1

创建文件夹c:\ bin并添加到您的路径并进行硬链接(如您所说的那样)会缩短字符串。也许将变量pf添加到具有值c:\ Program Files的系统变量中,然后用路径中的%pf%替换c:\ Program Files。

编辑:

创建一个虚拟驱动器。替代p:“ c:\ program files”


1
我认为路径将包含扩展的变量,在这种情况下,它不会变得更短。
Ben Voigt 2010年

0

我按照以下步骤使条目易于管理:

  1. 为软件包用法的不同组合创建了不同的用户。示例:(a)创建一个用户网络,以使所有网络开发软件可用;(b)创建一个用户数据库,以使所有数据库和数据仓库软件包可用。请记住,某些软件可能会创建多个条目。或有时我将其分为特定于oracle,特定于MSSQL和特定于oracle的用户。我将MySQL / PostgreSQL,tomcat,wamp,xamp全部放入用户帐户webr。

  2. 如果可能,请安装通用软件包,如office,photoshop,..作为对所有用户可用的系统专用软件包,以及作为用户特定的特殊软件包。当然,我必须登录到不同的用户并安装它们。并非所有软件都可以提供此选项。如果“仅为此用户安装”选项不可用,请在整个系统上安装它。

  3. 我避免将程序安装到文件夹Program File(x86)或Program File中。我总是安装到基本目录中。例如,MySQL 64位进入“ C:\ mysql64”,而MySQL 32位进入“ C:\ mysql”文件夹。我总是假设仅为64位软件添加后缀64。如果没有后缀,则为32位。我对Java和其他人也遵循相同的原则。这样,我的路径将更短,不包括“ C:\ Program File(x86)”。对于某些软件,可能需要编辑配置文件以显示.exe文件的确切位置。只有需要安装到“ C:\ Program File(x86)”中的程序才会安装到该文件夹​​中。我总是记得要缩短名字。我避免使用类似tomcat / release / version-2.5.0.3这样的版本号。如果我需要知道版本,我通过名称版本创建文件,并将其放入tomcat文件夹。通常,请尽可能缩短链接。

  4. 如果上述所有步骤均超过Windows限制,则包括任何批处理以替换指向该路径的缩写链接。

然后登录到特定于用法的(移动应用程序,数据库/数据仓库或Web开发...)用户并执行相关任务。

您也可以在Windows中创建虚拟窗口。只要您拥有一个许可的OS副本,就可以使用相同的密钥创建多个虚拟窗口。您可以将特定于特定任务的软件包放入该计算机中。您每次必须启动单独的VM。一些内存密集型软件包,例如3D动画电影制作者,都应该放到主机中,而不是放到VM中,因为VM只有一部分可用的RAM。但是,启动每个VM都很麻烦。


0

上述解决方案仅在您可以缩小路径的情况下有效。就我而言,这并不是真正的选择,每次我打开命令提示符时都必须运行脚本是一件麻烦事。因此,我编写了一个简单的脚本,该脚本在打开命令提示符时自动运行,并将文本文件的内容附加到您的路径中。

在某些情况下,运行此脚本会使事情中断(例如,在github或cygwin shell中),因此我还添加了一个包含路径列表的文件,如果在其中启动了命令提示符,则路径变量为不会通过通常会更新路径的启动脚本进行更改。

@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

而且Path.txt看起来像

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;

虽然Dontsetup.txt看起来像

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

要使其在启动时自动运行,请打开regedit,导航至HKEY_LOCAL_MACHINE / SOFTWARE / Microsoft / Command Processor,然后右键单击右侧的内容,然后按new-> Multi-String Value。将其命名为“自动运行”。将其值设置为

C:\Users\Yams\setUpPath.bat

或您在上面存储批处理文件的其他位置。


0

没尝试过,但是将PATH分成多个部分工作并将它们加入最终变量工作中可以吗?

最初的示例假设您有类似

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

相反,您创建:

_PATH1 = {LONGPATH1};{LONGPATH2};....{2048 char}
_PATH2 = {2049th char}...{LONGPATH_N-1};{LONGPATH_N}
rem // may be more parts
PATH = %_PATH1%;%_PATH2%
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.