Як уникнути перенаселення змінної середовища PATH у Windows?


115

Я хотів би знати, які підходи ви використовуєте для керування виконуваними файлами у вашій системі. Наприклад, у мене є майже все, що доступне через командний рядок, але тепер я підійшов до межі рядка шляху, тому я не можу додати більше dir.

Отже, що ти рекомендуєш? Давно я намагався використовувати softLinks виконуваних файлів у Dir, який належав до шляху, але такий підхід не спрацював. Перекиньте "виконуваний файл" лише на відомий Dir, є проблеми, що практично будь-яка програма вимагає набору файлів, тому це також погано. Перекиньте виконуваний файл і всі його файли у відомий Dir, ммм, це спрацює, але можливість отримати конфлікт у назві файлів дуже велика. Створити жорстку посилання? не знаю. Що ти думаєш?


чому ти використовуєш так багато шляхів? шлях зазвичай використовується для загального режиму, коли ваш додаток повинен ділитися розширеним об'єктом / додатком / lib з іншими. Використовуйте стільки, щоб зробити додаток повільніше. Чи можете ви детальніше розповісти про те, як ви використовуєте, створюєте var середовище шляху?
пінічі

1
привіт, пінічі, дуже багато додатків використовують стандартний "C: \ програмний файл \ 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файли.

EDIT 2: У коментарі Бена Войта до іншої відповіді зазначається, що використання інших змінних середовища, як пропонується, може не зменшити тривалість, %PATH%оскільки вони будуть розширені до зберігання. Це може бути правдою, і я цього не перевіряв. Ще одним варіантом є використання форм 8dot3 для довших імен каталогів, наприклад, C:\Program Filesяк правило, еквівалентно C:\PROGRA~1. Ви можете використовувати dir /xдля перегляду коротших імен.

EDIT 3: Цей простий тест змушує мене повірити, що Бен Фогт має рацію.

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

Наприкінці цього ви бачите вихід, hellohelloа не результат byehello.

EDIT 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 на основі системного шляху та додати будь-який інший Dir. Всі ці підходи мають тип "компактна ця струна", але чи можемо ми мати централізований каталог бінарних файлів, як це має Unix?
mjsr

1
Хм, що стосується дуже довгих каталогів, я думаю, що все навпаки: чим довше каталог, тим більше символів ви зберігаєте, використовуючи формат 8dot3. Якщо важко орієнтуватися cmd, зверніть увагу, що ви можете використовувати *для збереження набору тексту. Так, наприклад, від root введіть dir /x pro*. Ви побачите потрібний каталог там разом з його назвою 8dot3. Потім використовуйте cdдля переходу до нього та повторіть процес.
Мітч Шварц

1
Що стосується UNIX, то там у вас $PATHпрацює дуже схоже на %PATH%Windows, тож я не впевнений, який саме ваш погляд. За умовами, імена каталогів UNIX, як правило, коротші, ніж у Windows, і, як наслідок, $PATHтакож є коротшими.
Мітч Шварц

2
Дякую Мітч, редактор 4, який ви надаєте, - це те, що я хотів! Тепер я можу мати централізовану папку з усіма бінарними файлами, які мені потрібні. Я буду тестувати докладніше, щоб побачити, чи є проблема з якоюсь програмою
mjsr

2
Ваш розділ "редагувати 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
Це було також корисно, оскільки воно розповіло мені про всі неіснуючі каталоги на моєму шляху, що накопичилися з часом.
Нейт Гленн

27
Швидкий редактор довкілля - ще один спосіб зробити це. Він виділяє неіснуючі каталоги та має опцію "перетворити довгий шлях у короткий".
Рассел Галлоп

3
@RussellGallop: це, сер, чудовий інструмент.
elo80ka

1
Зверніть увагу на відсутність після завершення пропозиції %%~sa. Я спробував оновити відповідь, але це не дозволить мені, якщо я не зміню 6 символів
zr870,

28

якщо ви використовуєте Windows Vista або новішу версію, ви можете зробити символьне посилання на папку. наприклад:

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

зробила б посилання c:\pf, як і ваша program filesпапка. Я виголив 300 символів зі свого шляху, використовуючи цей трюк.


Це приємна альтернатива використанню змінної середовища для представлення часткового шляху.
porcus

1
Це, безумовно, допоможе більше, але якщо ви хочете більш "правильне" (підтримується?) Рішення, ви можете замінити екземпляри c:\Program Filesта c:\Program Files (x86)заздалегідь визначені змінні %ProgramFiles%та %ProgramFiles(x86)% tenforums.com/tutorials/… Вони зберігають лише кілька символів кожен , але якщо ви дійсно на межі збільшення PATH, це може бути різницею. З цього питання я збираюся створити% pf% та% pfx%, які відповідають правильним шляхам. Дякую за ідею! :)
rainabba

Проблема з використанням змінних, таких як% pf% та% pfx%, полягає в тому, що у вас виникають ті самі проблеми, що і при створенні символічних посилань - оновлення програмного забезпечення можуть знову додавати речі до змінної шляху. Інша проблема використання подібних змінних полягає в тому, що не швидко і просто скриптувати речі навколо нього або переглядати їх у Explorer. Використовуючи описаний мною метод, ви можете буквально відкрити c: \ PF. Windows бачить це просто як папку, тому ви можете легко писати bat або powerhell проти нього.
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%

Я вважаю такий підхід відносно чистим і ще не маю проблем із цим.


7

Я, як правило, не хвилююся з цього приводу (я не зіткнувся з обмеженням розміру шляху - я навіть не знаю, що це в сучасних системах Windows), але ось що я можу зробити, щоб не ставити каталог каталогу в Шлях:

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

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

що по суті створює псевдонім для команди. Це не обов'язково ідеально. Деякі програми дійсно наполягають на тому, що вони перебувають на шляху (що досить рідко зараз), а інші програми, які намагаються викликати його, можуть не знайти його належним чином. Але для більшості застосувань це працює добре.

Але взагалі мені не довелося переживати, щоб уникнути додавання каталогів у шлях.


Коли ви почнете слідувати цьому "шляху", будьте уважні, що пакетний сценарій не може викликати інший пакетний сценарій без синтаксису "CALL [bat]". Отже, якщо ви хочете переконатися, що ваш пересланий або не виконаний виклик викликається від bat, використовуйте "call php script.php" замість просто "php script.php" (який працює обома способами) Відмінна причина для використання. bat диспетчер, щоб запобігти конфліктам імен PATH (множинна версія того ж exe)
131

@ 131: Ви б не хотіли пояснити, що ви маєте на увазі під цим "шляхом"? Ви маєте на увазі конкретний шлях до файлу з прикладу? А точніше загальний метод, запропонований цією відповіддю?
АБО Mapper

@ORMapper: коли 131 каже: "Коли ви починаєте слідувати цьому" шляху ", він означає:" Коли ви використовуєте цю техніку ".
Майкл Берр

1
Як ви писали, "інші програми, які намагаються викликати його, можуть не знайти його належним чином" - натомість: На жаль, він може передавати автоматичні дзвінки до програм командного рядка, наприклад, за допомогою інструментів побудови, таких як NAnt, поза курсом. Виправлення викликає команду заздалегідь створеною cmd /c, але це, в свою чергу, означає, що сценарій збірки стає специфічним для Windows: / Я про це запитав в окремому запитанні .
АБО Mapper

5

Інша ідея: Використовуйте DIR / X для визначення коротких імен, згенерованих для імен файлів, які не є 8dot3. Потім використовуйте їх у вашому% PATH%.

Наприклад, "C: \ Program Files" стає "C: \ PROGRA ~ 1".


1
На жаль, я щойно зрозумів, що це вже запропонував @Mitch. Я збираюся дати йому +1 за це. :)
Android Eve


2

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

Всі програми CLI, які я використовую (вузол, php, python, git, svn, rsync, plink ...), якими я користуюсь, є насправді тим самим файлом EXE (близько 10 кб, який я просто називаю по-різному), який я вкладаю в один і той же каталог. Макетний статичний чіткий текстовий файл робить "ім'я проксі-файлу для реального відображення exe".

Диспетчер використовує API низького рівня управління win32, щоб бути абсолютно прозорим.

За допомогою цього програмного забезпечення у моєму PATH для всіх програм, які я можу використовувати, у мене встановлено ОДИН додатковий каталог.


1

Створення папки c: \ bin, додавання до вашого шляху та жорстке посилання, як ви сказали, може скоротити рядок. Можливо, додайте змінну pf до системного vars зі значенням c: \ Program Files, а потім замініть c: \ Program Files на шлях% pf%.

Редагувати:

Створіть віртуальний привід. subst p: "c: \ програмні файли"


1
Я думаю, що шлях міститиме розширені змінні, і в цьому випадку він не стане коротшим.
Бен Войгт

0

Я виконую ці кроки, щоб зробити записи керованими:

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

  2. Якщо можливо, встановіть загальні пакети, такі як Office, Photoshop, .. як специфічні для системи, доступні для всіх користувачів, і спеціальні пакети як конкретні для користувача. Звичайно, мені довелося увійти до різних користувачів і встановити їх. Не все програмне забезпечення може надавати цю опцію. Якщо опція "встановити лише для цього користувача" недоступна, встановіть її для всієї системи.

  3. Я уникаю встановлення програм у папку Program File (x86) або у програму File. Я завжди встановлюю в базовий каталог. Наприклад, 64-бітний MySQL переходить у "C: \ mysql64", а 32-бітний MySQL переходить у папку "C: \ mysql". Я завжди припускаю додавати суфікс 64 лише для 64-бітного програмного забезпечення. Якщо суфікса немає, то це 32 біт. Я слідую за тим самим Явою та іншими. Таким чином мій шлях буде коротшим, не враховуючи "C: \ Program File (x86)". Для певного програмного забезпечення файл конфігурації може знадобитися відредагувати, щоб показати, де саме знаходиться .exe-файл. У цю папку буде встановлена ​​лише програма, яка потребує встановлення у "C: \ Program File (x86)". Завжди пам’ятаю, щоб скоротити імена. Я уникаю номера версії, як tomcat / release / version-2.5.0.3 таких деталей. Якщо мені потрібно знати нову версію, Я створюю файл за версією імені і вкладаю його в папку tomcat. Загалом, максимально скорочуйте посилання.

  4. Включіть будь-яку партію для заміни скороченого посилання на шлях, якщо всі вищезазначені кроки пройшли ліміт Windows.

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

Ви також можете створити віртуальне вікно всередині вікон. Поки у вас є одна ліцензована копія ОС, можливо створити кілька віртуальних вікон з одним ключем. Ви можете розмістити пакети, специфічні для певної задачі, на цій машині. Вам потрібно кожного разу запускати окремий VM. Деякі пакети, що займають велику пам’ять, такі як виробники 3D-анімаційних фільмів, повинні бути розміщені в основній машині, а не у VM, оскільки VM матиме лише частину оперативної пам’яті. Боляче завантажувати кожен VM, хоча.


0

Наведені вище рішення працюють лише в тому випадку, якщо ви можете обрізати свій шлях. У моєму випадку це насправді не було варіантом, і це було зайвим клопотанням запускати сценарій кожного разу, коли я відкривав командний рядок. Тому я написав простий скрипт, який автоматично запускається під час відкриття командного рядка та додає вміст текстового файлу до вашого шляху.

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

@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, потім клацніть правою кнопкою миші праворуч і натисніть нову -> Multi-String Value. Назвіть це AutoRun. Встановіть значення

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%
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.