Как избежать чрезмерного заполнения переменной среды PATH в Windows?

115

Я хотел бы знать, какие подходы вы используете для управления исполняемыми файлами в вашей системе. Например, у меня есть почти все, что доступно через командную строку, но теперь я подошел к пределу строки пути, поэтому я не могу добавить больше dir.

Так что посоветуете? Давным-давно я пытался использовать softLinks исполняемых файлов в Dir, принадлежащем пути, но этот подход не работал. Бросить "только исполняемый файл" в известный каталог, есть проблемы, что почти любое приложение требует набора файлов, так что это тоже плохо. Бросьте исполняемый файл и все его файлы в известный каталог, ммм, это сработает, но вероятность возникновения конфликта в имени файлов очень высока. Создать HardLink? я не знаю. Что вы думаете?

mjsr
источник
почему вы используете столько путей? path обычно используется для common dir, когда ваше приложение должно делиться расширением object / app / lib с другими. Используйте столько, чтобы приложение запускалось медленнее. Не могли бы вы подробнее рассказать о том, как вы используете create path environment var?
pinichi
1
привет, пиничи, многие приложения используют стандартный "C: \ Program File \ AppNAme \ ...", и в моем случае многие из этих приложений могут работать в режиме командной строки или должны быть доступны другим приложениям ( например исполняемые файлы Miktex, которые ожидает любой редактор Tex), поэтому они должны быть в PATH. Я не хочу знать лучшего подхода, потому что мой неустойчивый
mjsr
1
Этот инструмент сжимает пути. Результат впечатляет: uweraabe.de/Blog/2014.09.09/the-garbled-path-variable/#more-337
InTheNameOfScience

Ответы:

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: В комментарии Бена Фойгта к другому ответу упоминается, что использование других переменных среды, как было предложено, может не уменьшить длину, %PATH%потому что они будут расширены перед сохранением. Это может быть правдой, и я не проверял это. Другой вариант - использовать формы 8dot3 для более длинных имен каталогов, например, C:\Program Filesкак правило, эквивалент C:\PROGRA~1. Вы можете использовать, dir /xчтобы увидеть более короткие имена.

РЕДАКТИРОВАТЬ 3: Этот простой тест заставляет меня поверить, что Бен Фойгт прав.

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%

Как правило, вы должны быть осторожны с запуском командных файлов из Интернета, поскольку вы можете делать с ними все, что угодно, например, форматировать жесткий диск. Если вы не доверяете приведенному выше коду (который я написал), вы можете протестировать его, заменив строку

%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
1
Хм, что касается очень длинных каталогов, я думаю, что верно обратное: чем длиннее каталог, тем больше символов вы сохраняете, используя формат 8dot3. Если трудно ориентироваться cmd, обратите внимание, что вы можете использовать *для экономии ввода. Так, например, из root введите dir /x pro*. Вы увидите желаемый каталог вместе с его именем 8dot3. Затем используйте cdдля перехода к нему и повторите процесс.
Митч Шварц
1
Что касается UNIX, у вас есть система, $PATHкоторая работает очень аналогично %PATH%Windows, поэтому я не уверен, в чем именно вы заключаете. По соглашению, имена каталогов UNIX обычно короче, чем в Windows, и в результате $PATHтакже имеют тенденцию быть короче.
Митч Шварц
2
Спасибо, Митч, предоставленный вами Edit 4 - это то, что я хотел! Теперь у меня есть централизованная папка со всеми необходимыми двоичными файлами. Я собираюсь провести более глубокое тестирование, чтобы увидеть, есть ли проблема с каким-либо приложением
mjsr
2
Ваш раздел "edit 4" слишком сложен для передачи аргументов исполняемому файлу. См. Ответ Майкла Берра.
Дэйв Андерсен
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
2
Это было также полезно, потому что в нем рассказывалось обо всех несуществующих каталогах на моем пути, которые накопились с течением времени.
Nate Glenn
27
Rapid Environment Editor - еще один способ сделать это. Он выделяет несуществующие каталоги и имеет опцию «преобразовать длинный путь в короткий».
Рассел Галлоп
3
@RussellGallop: это, сэр, отличный инструмент.
elo80ka
1
Обратите внимание на отсутствующую заключительную цитату после %%~sa. Я попытался обновить ответ, но он не позволит мне, если я не изменю 6 символов
zr870
28

если вы используете Windows Vista или выше, вы можете сделать символическую ссылку на папку. например:

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

сделал бы ссылку, чтобы c:\pfбыла ваша program filesпапка. Используя этот трюк, я убрал со своего пути 300 символов.

bmg002
источник
Это хорошая альтернатива использованию переменной среды для представления частичного пути.
porcus
1
Это определенно поможет больше, но если вы хотите более «правильное» (поддерживаемое?) Решение, вы можете заменить экземпляры c:\Program Filesи c:\Program Files (x86)на предварительно определенные переменные %ProgramFiles%и %ProgramFiles(x86)% tenforums.com/tutorials/… Они сохранят только несколько символов каждый , но если вы ДЕЙСТВИТЕЛЬНО находитесь на грани максимального использования PATH, разница может быть в этом. В этом отношении я собираюсь создать% pf% и% pfx%, которые разрешают правильные пути. Спасибо за идею! :)
rainabba
Проблема с использованием таких переменных, как% pf% и% pfx%, заключается в том, что вы получаете те же проблемы, что и при создании символических ссылок - обновления программного обеспечения могут снова добавлять элементы в переменную пути. Другая проблема с использованием подобных переменных заключается в том, что не так быстро и легко создать сценарии вокруг них или перейти к ним из проводника. Используя описанный мной метод, вы можете буквально открыть c: \ PF. Windows видит его как папку, так что вы можете легко написать bat или powershell.
bmg002
10

Если кому-то интересно ...

Я обнаружил, что мне никогда не нужны все эти пути сразу, поэтому я создаю кучу командных файлов «инициализации», которые соответственно изменяют путь.

Например, если бы я хотел заняться разработкой на C ++ в Eclipse, я бы сделал:

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

Я считаю этот подход относительно чистым и пока не сталкивался с какими-либо проблемами.

YellPika
источник
7

Обычно мне не нужно об этом беспокоиться (я не сталкивался с ограничением размера пути - я даже не знаю, что это такое в современных системах Windows), но вот что я могу сделать, чтобы не помещать каталог программы в тропинка:

  • большинство утилит командной строки попадают в c:\util каталог, который находится на пути
  • в противном случае я добавлю в c:\utilкаталог простой cmd / batch-файл, который выглядит примерно так:

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

который по сути создает псевдоним для команды. Это не обязательно идеально. Некоторые программы действительно настаивают на том, чтобы быть на пути (в настоящее время это довольно редко), а другие программы, которые пытаются его вызвать, могут не найти его должным образом. Но для большинства случаев он работает хорошо.

Но в целом мне не приходилось беспокоиться о том, чтобы избежать добавления каталогов в путь.

Майкл Берр
источник
Когда вы начинаете следовать по этому «пути», помните, что пакетный сценарий не может вызвать другой пакетный сценарий без синтаксиса «CALL [bat]». Итак, если вы хотите убедиться, что ваш exe-файл с переадресацией или нет вызывается из летучей мыши, используйте «call php script.php» вместо просто «php script.php» (который работает в обоих направлениях). Отличная причина для использования. bat dispatcher предназначен для предотвращения конфликтов имен PATH (кратная версия одного и того же exe)
131
@ 131: Не могли бы вы объяснить, что вы подразумеваете под «этим« путем »»? Вы имеете в виду конкретный путь к файлу из примера? Или, скорее, общий метод, предложенный этим ответом?
OR Mapper
@ORMapper: когда 131 говорит: «Когда ты начинаешь следовать по этому« пути »», он имеет в виду «Когда ты используешь эту технику».
Майкл Берр
1
Как вы писали, «другие программы, которые пытаются его вызвать, могут не найти его должным образом» - показательный пример: к сожалению, он может автоматически вызывать приложения командной строки, например, с помощью таких инструментов сборки, как NAnt, конечно. Средство исправления - это вызов команды с добавлением cmd /cв начале, но это, в свою очередь, означает, что сценарий сборки становится специфичным для Windows: / Я спросил об этом в отдельном вопросе .
OR Mapper
5

Другая идея: используйте DIR / X для определения коротких имен, созданных для имен файлов, отличных от 8dot3. Затем используйте их в своем% PATH%.

Например, «C: \ Program Files» становится «C: \ PROGRA ~ 1».

Android Eve
источник
1
Ой, я только что понял, что это уже было предложено @Mitch. Я собираюсь поставить ему за это +1. :)
Android Eve
2

Я написал и постоянно использую стандартный поток (stdin / stderr / stdout) и программу PROXY с кодом выхода (называемую диспетчером https://github.com/131/dispatcher )

Все программы CLI, которые я использую (node, php, python, git, svn, rsync, plink ...), которые я использую, на самом деле являются одним и тем же файлом exe (около 10 КБ, я просто называю его по-другому), который я вставляю в тот же каталог. Фиктивный статический открытый текстовый файл выполняет «имя прокси-файла для реального сопоставления exe».

Диспетчер использует низкоуровневый API Win32 для управления процессами, чтобы быть абсолютно прозрачным.

Используя это программное обеспечение, в моем PATH установлен только ОДИН дополнительный каталог для всех программ, которые я могу использовать.

131
источник
1

Создание папки c: \ bin, добавление к вашему пути и жесткая ссылка, как вы сказали, может сократить строку. Возможно, добавьте переменную pf в системные переменные со значением c: \ Program Files, затем замените c: \ Program Files на% pf% в пути.

Редактировать:

Создайте виртуальный диск. subst p: "c: \ program files"

troynt
источник
1
Я думаю, что путь будет содержать расширенные переменные, и в этом случае он не станет короче.
Бен Фойгт
0

Я выполняю следующие шаги, чтобы сделать записи управляемыми:

  1. Создал разных пользователей для разных комбинаций использования программных пакетов. Пример: (a) Создал пользовательскую сеть для предоставления доступа ко всему программному обеспечению для веб-разработки; (b) Создана база данных пользователей для предоставления доступа ко всем программным пакетам баз данных и хранилищ данных. Помните, что некоторые программы могут создавать более одной записи. Или когда-нибудь я разбиваю это на конкретных пользователей оракула и конкретных пользователей MSSQL и конкретных пользователей оракула. Я поместил MySQL / PostgreSQL, tomcat, wamp, xamp все в учетную запись пользователя webr.

  2. Если возможно, установите общие пакеты, такие как office, photoshop, .. в зависимости от системы, доступные для всех пользователей и специальные пакеты для конкретных пользователей. Конечно, мне приходилось входить в систему разных пользователей и устанавливать их. Не все программное обеспечение может предоставлять эту возможность. Если опция «установить только для этого пользователя» недоступна, установите ее для всей системы.

  3. Я избегаю установки программ в папку Program File (x86) или в Program File. Я всегда устанавливаю в базовый каталог. Например, 64-разрядная версия MySQL помещается в папку «C: \ mysql64», а 32-разрядная версия MySQL - в папку «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.

Затем войдите в систему конкретного пользователя (мобильное приложение, база данных / хранилище данных или веб-разработка .. ..) и выполните соответствующие задачи.

Вы также можете создавать виртуальные окна внутри окон. Пока у вас есть одна лицензионная копия ОС, возможно создание нескольких виртуальных окон с одним и тем же ключом. Вы можете поместить на этот компьютер пакеты, предназначенные для конкретной задачи. Приходится каждый раз запускать отдельную виртуальную машину. Некоторые пакеты, интенсивно использующие память, например, создатели 3D-анимационных фильмов, должны быть помещены в основную машину, а не в виртуальную машину, поскольку виртуальная машина будет иметь только часть оперативной памяти, доступной для ее использования. Однако загружать каждую виртуальную машину - это боль.

Д-р А. Анукант
источник
0

Приведенные выше решения работают, только если вы можете сократить свой путь. В моем случае это был не вариант, и мне было сложно запускать скрипт каждый раз, когда я открывал командную строку. Поэтому я написал простой скрипт, который запускается автоматически при открытии командной строки и добавляет содержимое текстового файла к вашему пути.

Есть также некоторые контексты, в которых запуск этого скрипта нарушает работу (скажем, в оболочке github или cygwin), поэтому я также добавил файл, содержащий список путей, которые, если в них запускается командная строка, переменная пути не Не изменяется с помощью сценария запуска, который обычно обновляет путь.

@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, затем щелкните правой кнопкой мыши справа и нажмите новый -> Многострочное значение. Назовите его AutoRun. Установите значение на

C:\Users\Yams\setUpPath.bat

или где еще вы сохранили командный файл выше.

Phylliida
источник
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%
Филипп Мунин
источник