Jak uniknąć przepełnienia zmiennej środowiskowej PATH w systemie Windows?

115

Chciałbym wiedzieć, jakie są podejścia, których używasz do zarządzania plikami wykonywalnymi w systemie. Na przykład mam prawie wszystko, co jest dostępne z linii poleceń, ale teraz doszedłem do granicy ciągu ścieżki, więc nie mogę dodać więcej dir.

Więc co polecasz? Dawno temu próbowałem użyć miękkich linków plików wykonywalnych w katalogu należącym do ścieżki, ale to podejście nie działało. Wrzuć „tylko plik wykonywalny” do znanego katalogu, ma problemy z tym, że prawie każda aplikacja wymaga zestawu plików, więc to również jest złe. Wrzuć plik wykonywalny i wszystkie jego pliki do znanego katalogu, mmm to zadziała, ale możliwość wystąpienia konfliktu w nazwie plików jest bardzo duża. Utworzyć HardLink? Nie wiem. Co myślisz?

mjsr
źródło
dlaczego używasz tak wielu ścieżek? ścieżka jest zwykle używana dla wspólnego katalogu, gdy aplikacja musi udostępniać innym obiektom rozszerzenie / aplikację / bibliotekę. Używaj tak dużo, aby aplikacja uruchamiała się wolniej. Czy możesz podać więcej szczegółów na temat tego, jak używasz, tworzysz zmienną ścieżkę środowiska?
pinichi
1
cześć pinichi, wiele aplikacji używa standardowego „C: \ Program File \ AppNAme \ ...”, aw moim przypadku wiele z tych aplikacji może działać z linii poleceń lub musi być dostępne dla innych aplikacji ( na przykład pliki wykonywalne Miktexa, których istnienia spodziewa się każdy edytor Tex), więc muszą one znajdować się w PATH. Nie chcę znać lepszego podejścia, ponieważ moje jest niezrównoważone
mjsr
1
To narzędzie skompresuje ścieżki. Wynik jest imponujący: uweraabe.de/Blog/2014/09/09/the-garbled-path-variable/#more-337
InTheNameOfScience

Odpowiedzi:

84

Jednym ze sposobów, które przychodzą mi do głowy, jest użycie innych zmiennych środowiskowych do przechowywania częściowych ścieżek; na przykład, jeśli masz

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

następnie możesz utworzyć nową zmienną środowiskową, taką jak

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

po którym stają się twoje oryginalne ścieżki

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

EDYCJA: Inną opcją jest utworzenie binkatalogu zawierającego .batpliki wskazujące na odpowiednie .exepliki.

EDYCJA 2: Komentarz Bena Voigta do innej odpowiedzi wspomina, że ​​użycie innych zmiennych środowiskowych zgodnie z sugestią może nie skrócić długości, %PATH%ponieważ zostałyby rozwinięte przed zapisaniem. Może to prawda i nie testowałem tego. Inną opcją jest jednak użycie formularzy 8dot3 dla dłuższych nazw katalogów, na przykład C:\Program Fileszazwyczaj jest to odpowiednik C:\PROGRA~1. Możesz użyć, dir /xaby zobaczyć krótsze nazwy.

EDYCJA 3: Ten prosty test prowadzi mnie do przekonania, że ​​Ben Voigt ma rację.

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

Na końcu zobaczysz hellohelloraczej wyjście niż byehello.

EDYCJA 4: W przypadku, gdy zdecydujesz się użyć plików wsadowych do wyeliminowania niektórych ścieżek %PATH%, możesz martwić się, jak przekazać argumenty z pliku wsadowego do pliku wykonywalnego, aby proces był przezroczysty (tj. Nie zauważysz żadnej różnicy między wywołaniem pliku wsadowego a wywołaniem pliku wykonywalnego). Nie mam dużego doświadczenia w pisaniu plików wsadowych, ale wydaje się, że działa dobrze.

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

Zasadniczo należy zachować ostrożność podczas uruchamiania plików wsadowych z Internetu, ponieważ z plikami wsadowymi można wykonywać różne czynności, takie jak formatowanie dysku twardego. Jeśli nie ufasz powyższemu kodowi (który napisałem), możesz go przetestować, zastępując wiersz

%actualdir%\%actualfile% %args%

z

echo %actualdir%\%actualfile% %args%

Idealnie byłoby, gdybyś dokładnie wiedział, co robi każda linia, zanim ją uruchomisz.

Mitch Schwartz
źródło
1
forma 8dot3 działa dobrze, ale dla katalogów naprawdę duże nie jest zbyt duże, na przykład „C: \ Program Files (x86) \ Microsoft Visual Studio 2008 SDK \ VisualStudioIntegration \ Tools \ Sandcastle \ ProductionTools \”. Inną rzeczą, która trochę zaoszczędziła, było to, że jako użytkownik mogłem utworzyć zmienną PATH opartą na ścieżce systemowej i dodać dowolny inny katalog. Wszystkie te podejścia są typu „kompaktowanie tego ciągu”, ale czy możemy mieć scentralizowany katalog plików binarnych, tak jak w przypadku Uniksa?
mjsr
1
Hmm, jeśli chodzi o bardzo długie katalogi, wydaje mi się, że jest odwrotnie: im dłuższy katalog, tym więcej znaków zapisujesz używając formatu 8dot3. Jeśli nawigacja jest trudna cmd, pamiętaj, że możesz użyć, *aby zaoszczędzić pisanie. Na przykład od roota wpisz dir /x pro*. Zobaczysz tam żądany katalog wraz z jego nazwą 8dot3. Następnie użyj, cdaby przejść do niego i powtórz proces.
Mitch Schwartz
1
Jeśli chodzi o UNIX, masz, $PATHktóry działa bardzo podobnie do %PATH%systemu Windows, więc nie jestem pewien, o co ci chodzi. Zgodnie z konwencją nazwy katalogów w systemie UNIX są zazwyczaj krótsze niż w systemie Windows, w wyniku czego są $PATHrównież krótsze.
Mitch Schwartz
2
Dzięki Mitch, Edycja 4, którą podałeś, jest tym, czego chciałem! Teraz mogę mieć scentralizowany folder ze wszystkimi plikami binarnymi, których potrzebuję. Zamierzam dokładniej przetestować, czy jest problem z jakąś aplikacją
mjsr
2
Twoja sekcja „edit 4” jest zbyt skomplikowana, jeśli chodzi o przekazywanie argumentów do pliku wykonywalnego. Zobacz odpowiedź Michaela Burra.
Dave Andersen
83

Spowoduje to przeanalizowanie zmiennej środowiskowej% PATH% i przekonwertowanie każdego katalogu na jego odpowiednik skróconej nazwy, a następnie złożenie wszystkiego w całość:

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

Weź dane wyjściowe i zaktualizuj zmienną PATH w zmiennych środowiskowych.

Todd Smith
źródło
Dziękuję, że to było bardzo przydatne! Skróciło moją drogę z 1990 do 1338 roku i wszystko nadal działa jak urok! Wybrałem Twoje podejście, ponieważ chciałem trzymać wszystko na swojej drodze, a łączenie plików wsadowych byłoby zbyt czasochłonne. DZIĘKI!
ndrizza
2
Było to również przydatne, ponieważ informowało mnie o wszystkich nieistniejących katalogach na mojej ścieżce, które nagromadziły się w czasie.
Nate Glenn
27
Rapid Environment Editor to kolejny sposób na zrobienie tego. Podświetla nieistniejące katalogi i ma opcję "przekonwertować długą ścieżkę na krótką".
Russell Gallop
3
@RussellGallop: to, proszę pana, niesamowite narzędzie.
elo80ka
1
Zwróć uwagę na brakujący cudzysłów zamykający po %%~sa. Próbowałem zaktualizować odpowiedź, ale nie pozwoli mi to, chyba że zmienię 6 znaków
zr870
28

jeśli używasz systemu Windows Vista lub nowszego, możesz utworzyć symboliczne łącze do folderu. na przykład:

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

utworzy łącze, podobnie jak c:\pfTwój program filesfolder. Używając tej sztuczki, ogoliłem 300 znaków z mojej ścieżki.

bmg002
źródło
Jest to fajna alternatywa dla używania zmiennej środowiskowej do reprezentowania częściowej ścieżki.
porcus
1
To zdecydowanie by pomogło bardziej, ale jeśli chcesz bardziej "poprawnego" (obsługiwanego?) Rozwiązania, możesz zastąpić wystąpienia c:\Program Filesi c:\Program Files (x86)wstępnie zdefiniowanymi zmiennymi %ProgramFiles%oraz %ProgramFiles(x86)% tenforums.com/tutorials/ ... Każdy z nich oszczędza tylko kilka znaków , ale jeśli NAPRAWDĘ jesteś na skraju maksymalnego wykorzystania ŚCIEŻKI, może to być różnica. W tym celu utworzę% pf% i% pfx%, które będą rozwiązywać do prawidłowych ścieżek. Dzięki za pomysł! :)
rainabba
Problem z używaniem zmiennych, takich jak% pf% i% pfx%, polega na tym, że masz te same problemy, co przy tworzeniu dowiązań symbolicznych - aktualizacje oprogramowania mogą ponownie dodawać elementy do zmiennej ścieżki. Innym problemem związanym z używaniem takich zmiennych jest to, że nie jest szybkie i łatwe skryptowanie rzeczy wokół nich lub przeglądanie ich z poziomu eksploratora. Używając opisanej przeze mnie metody, możesz dosłownie otworzyć c: \ PF. Windows widzi go jak folder, więc możesz łatwo napisać na nim bat lub powershell.
bmg002
10

Na wypadek gdyby ktoś był zainteresowany ...

Uważam, że nigdy nie potrzebuję wszystkich tych ścieżek na raz, więc tworzę kilka plików wsadowych "inicjalizacyjnych", które odpowiednio modyfikują ścieżkę.

Na przykład, gdybym chciał zrobić coś w C ++ w Eclipse, zrobiłbym:

> initmingw
> initeclipse
> eclipse

Jest to również przydatne, aby uniknąć konfliktów między plikami wykonywalnymi o tej samej nazwie (takimi jak kompilatory C ++ i D, które mają program make.exe).

Moje pliki wsadowe zazwyczaj wyglądają tak:

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

Uważam, że to podejście jest stosunkowo czyste i nie napotkałem jeszcze żadnych problemów.

YellPika
źródło
7

Generalnie nie muszę się tym martwić (nie napotkałem ograniczenia rozmiaru ścieżki - nawet nie wiem, co to jest w nowoczesnych systemach Windows), ale oto, co mogę zrobić, aby uniknąć umieszczania katalogu programu w ścieżka:

  • większość narzędzi wiersza poleceń jest wrzucana do c:\utilkatalogu znajdującego się na ścieżce
  • w przeciwnym razie dodam prosty plik cmd / wsadowy do c:\utilkatalogu, który wygląda mniej więcej tak:

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

co zasadniczo tworzy alias dla polecenia. To niekoniecznie jest idealne. Niektóre programy naprawdę nalegają, aby znaleźć się na ścieżce (obecnie jest to dość rzadkie), a inne programy, które próbują go wywołać, mogą nie znaleźć go poprawnie. Ale w większości zastosowań działa dobrze.

Ale generalnie nie musiałem się martwić o unikanie dodawania katalogów do ścieżki.

Michael Burr
źródło
Kiedy zaczynasz podążać tą „ścieżką”, uważaj, że skrypt wsadowy nie może wywołać innego skryptu wsadowego bez składni „CALL [bat]”. Tak więc, jeśli chcesz mieć pewność, że twój plik exe przekazany lub nie jest wywoływany z nietoperza, użyj „call php script.php” zamiast po prostu „php script.php” (który działa w obie strony). Doskonały powód do użycia. bat dispatcher ma zapobiegać konfliktom nazw PATH (wielokrotna wersja tego samego exe)
131
@ 131: Czy mógłbyś wyjaśnić, co masz na myśli przez „tę„ ścieżkę ””? Czy masz na myśli konkretną ścieżkę do pliku z przykładu? Czy raczej ogólna metoda sugerowana przez tę odpowiedź?
LUB Mapper
@ORMapper: kiedy 131 mówi: „Kiedy zaczynasz podążać tą„ ścieżką ””, ma na myśli: „Kiedy używasz tej techniki”.
Michael Burr
1
Jak napisałeś, „inne programy, które próbują go wywołać, mogą go nie znaleźć poprawnie” - przykład: niestety może generować automatyczne wywołania do aplikacji wiersza poleceń, na przykład oczywiście przez narzędzia budujące, takie jak NAnt. cmd /cŚrodkiem zaradczym jest wywołanie polecenia z przedrostkiem , ale to z kolei oznacza, że ​​skrypt budujący staje się specyficzny dla systemu Windows: / Pytałem o to w osobnym pytaniu .
LUB Mapper
5

Inny pomysł: użyj DIR / X do określenia krótkich nazw generowanych dla nazw plików innych niż 8dot3. Następnie użyj ich w% PATH%.

Na przykład „C: \ Program Files” staje się „C: \ PROGRA ~ 1”.

Android Eve
źródło
1
Ups, właśnie zdałem sobie sprawę, że to już zasugerował @Mitch. Dam mu za to +1. :)
Android Eve
2

Za każdym razem napisałem i używam standardowego strumienia (stdin / stderr / stdout) i programu PROXY z kodem wyjścia (o nazwie dispatcher https://github.com/131/dispatcher )

Wszystkie programy CLI, których używam (node, php, python, git, svn, rsync, plink ...), których używam, są w rzeczywistości tym samym plikiem exe (około 10kb, który po prostu nazywam inaczej), który umieszczam w tym samym informator. Fikcyjny statyczny zwykły plik tekstowy wykonuje „nazwę pliku proxy na prawdziwe odwzorowanie exe”.

Dyspozytor używa niskopoziomowego interfejsu API Win32 do zarządzania procesami, aby zapewnić całkowitą przejrzystość.

Korzystając z tego oprogramowania, mam tylko JEDEN dodatkowy katalog ustawiony w mojej PATH dla wszystkich programów, których mogę używać.

131
źródło
1

Utworzenie folderu c: \ bin, dodanie do ścieżki i połączenie twarde, jak powiedziałeś, może skrócić ciąg. Może dodaj zmienną pf do zmiennych systemowych o wartości c: \ Program Files, a następnie zamień c: \ Program Files na% pf% w ścieżce.

Edytować:

Utwórz wirtualny dysk. subst p: "c: \ pliki programu"

troynt
źródło
1
Myślę, że ścieżka zawierałaby rozwinięte zmienne, w którym to przypadku nie byłaby krótsza.
Ben Voigt
0

Wykonuję następujące kroki, aby ułatwić zarządzanie wpisami:

  1. Utworzono różnych użytkowników dla różnych kombinacji wykorzystania pakietów oprogramowania. Przykład: (a) Utworzono witrynę internetową użytkownika w celu udostępnienia całego oprogramowania do tworzenia witryn internetowych; (b) Utworzono bazę danych użytkowników w celu udostępnienia całej bazy danych i pakietów oprogramowania do magazynowania danych. Pamiętaj, że niektóre programy mogą tworzyć więcej niż jeden wpis. Lub czasami dzielę to na użytkowników specyficznych dla Oracle, MSSQL i specyficznych dla Oracle. Umieściłem MySQL / PostgreSQL, tomcat, wamp, xamp wszystko na koncie użytkownika webr.

  2. Jeśli to możliwe, zainstaluj popularne pakiety, takie jak office, photoshop itp. Jako specyficzne dla systemu dostępne dla wszystkich użytkowników i specjalne pakiety jako specyficzne dla użytkownika. Oczywiście musiałem zalogować się do różnych użytkowników i je zainstalować. Nie wszystkie programy oferują tę opcję. Jeśli opcja „zainstaluj tylko dla tego użytkownika” nie jest dostępna, zainstaluj ją dla całego systemu.

  3. Unikam instalowania programów w folderze Program File (x86) lub w folderze Program File. Zawsze instaluję w katalogu podstawowym. Na przykład 64-bitowy MySQL trafia do folderu „C: \ mysql64”, a 32-bitowy MySQL do folderu „C: \ mysql”. Zawsze zakładam dodanie przyrostka 64 tylko dla oprogramowania 64-bitowego. Jeśli nie ma przyrostka, jest to wersja 32-bitowa. To samo podążam za Javą i innymi. W ten sposób moja ścieżka będzie krótsza, bez „C: \ Program File (x86)”. W przypadku niektórych programów może być konieczna edycja pliku konfiguracyjnego, aby pokazać, gdzie dokładnie znajduje się plik .exe. Tylko program wymagający instalacji w „C: \ Program File (x86)” zostanie zainstalowany w tym folderze. Zawsze pamiętam o skróceniu nazwisk. Unikam numerów wersji takich jak tomcat / release / version-2.5.0.3 takich szczegółów. Jeśli potrzebuję znanej wersji, Tworzę plik według nazwy wersji i umieszczam go w folderze tomcat. Ogólnie skracaj link tak bardzo, jak to możliwe.

  4. Dołącz dowolną wiązkę, aby zastąpić skrócone łącze do ścieżki, jeśli wszystkie powyższe kroki przekroczyły limit systemu Windows.

Następnie zaloguj się do użytkownika specyficznego dla użytkowania (aplikacja mobilna, baza danych / hurtownia danych lub tworzenie stron internetowych .. ..) i wykonaj odpowiednie zadania.

Możesz także tworzyć wirtualne okna w oknach. Jeśli masz jedną licencjonowaną kopię systemu operacyjnego, możliwe jest tworzenie wielu wirtualnych okien z tym samym kluczem. Możesz umieścić pakiety specyficzne dla określonego zadania na tym komputerze. Za każdym razem musisz uruchamiać oddzielną maszynę wirtualną. Niektóre pakiety wymagające dużej ilości pamięci, takie jak twórcy filmów animowanych 3D, powinny być umieszczane na głównej maszynie, a nie na maszynach wirtualnych, ponieważ maszyny wirtualne będą miały tylko część pamięci RAM dostępnej do użytku. Jednak uruchomienie każdej maszyny wirtualnej jest trudne.

Dr A. Anukanth
źródło
0

Powyższe rozwiązania działają tylko wtedy, gdy możesz skrócić swoją ścieżkę. W moim przypadku tak naprawdę nie była to opcja, a uruchamianie skryptu za każdym razem, gdy otwierałem wiersz polecenia, było kłopotliwe. Napisałem więc prosty skrypt, który uruchamia się automatycznie po otwarciu wiersza polecenia i dołącza zawartość pliku tekstowego do ścieżki.

Istnieją również konteksty, w których uruchomienie tego skryptu psuje rzeczy (powiedzmy, w powłoce github lub cygwin), więc dodałem również plik zawierający listę ścieżek, które, jeśli zostanie uruchomiony w nich wiersz polecenia, zmienna ścieżki to n 't zmieniono za pomocą skryptu startowego, który normalnie aktualizuje ścieżkę.

@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

A Path.txt będzie wyglądać mniej więcej tak

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;

Podczas gdy Dontsetup.txt będzie wyglądać mniej więcej tak

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

Aby uruchomić to automatycznie przy starcie, otwórz regedit, przejdź do HKEY_LOCAL_MACHINE / SOFTWARE / Microsoft / Command Processor, a następnie kliknij prawym przyciskiem myszy po prawej stronie i naciśnij nowy -> Wartość wielociągu. Nazwij to AutoRun. Ustaw jego wartość na

C:\Users\Yams\setUpPath.bat

lub w innym miejscu, w którym zapisałeś powyższy plik wsadowy.

Phylliida
źródło
0

Nie próbowałem tego, ale czy podzielenie PATH na części zadziała i połączenie ich w ostatecznej pracy ze zmiennymi?

Przykład początkowo powiedzmy, że masz coś takiego

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

Zamiast tego tworzysz:

_PATH1 = {LONGPATH1};{LONGPATH2};....{2048 char}
_PATH2 = {2049th char}...{LONGPATH_N-1};{LONGPATH_N}
rem // may be more parts
PATH = %_PATH1%;%_PATH2%
Philipp Munin
źródło