Windows'ta PATH Ortam Değişkeninin aşırı doldurulmasını nasıl önleyebilirsiniz?


115

Sisteminizdeki çalıştırılabilir dosyaları yönetmek için kullandığınız yaklaşımların neler olduğunu bilmek isterim. Örneğin, komut satırından erişilebilen hemen hemen her şeye sahibim, ancak şimdi yol dizesinin sınırına geldim, bu nedenle daha fazla dir ekleyemiyorum.

Peki ne tavsiye edersiniz? Uzun zaman önce, yürütülebilir dosyaların softLink'lerini yola ait bir Dir'de kullanmaya çalıştım, ancak bu yaklaşım işe yaramadı. "Yalnızca yürütülebilir" olanı bilinen bir dizine atın, hemen hemen her uygulamanın bir dizi dosya gerektirmesi gibi sorunları vardır, bu nedenle bu da kötüdür. Yürütülebilir dosyayı ve tüm dosyalarını bilinen bir dizine atın, mmm bu işe yarayacaktır, ancak dosyaların adına bir çakışma olasılığı çok yüksektir. HardLink mi oluşturacaksınız? bilmiyorum. Ne düşünüyorsun?


neden bu kadar çok yol kullanıyorsun? path, genellikle uygulamanızın ext object / app / lib'i başkalarıyla paylaşması gerektiğinde ortak dizin için kullanılır. Çok fazla uygulama kullanın, uygulamayı yavaşlatın. Yol ortamını nasıl kullandığınıza dair daha fazla ayrıntı verebilir misiniz?
pinichi

1
merhaba pinichi, pek çok uygulama standart "C: \ Program File \ AppNAme \ ..." kullanır ve benim durumumda bu uygulamaların çoğu komut satırı tarzında çalışabilir veya diğer uygulamalar tarafından erişilebilir olması gerekir ( örneğin, herhangi bir Tex editörünün olmasını beklediği Miktex çalıştırılabilirleri), bu yüzden PATH içinde olmaları gerekir. Benimki sürdürülemez olduğu için daha iyi bir yaklaşım bilmek
istemiyorum

1
Bu araç yolları sıkıştıracaktır. Sonuç etkileyici: uweraabe.de/Blog/2014/09/09/the-garbled-path-variable/#more-337
InTheNameOfScience

Yanıtlar:


84

Düşünebileceğim bir yol, kısmi yolları depolamak için diğer ortam değişkenlerini kullanmaktır; örneğin, eğer varsa

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

daha sonra yeni bir ortam değişkeni oluşturabilirsiniz.

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

daha sonra orijinal yollarınız olur

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

DÜZENLEME: Diğer bir seçenek, uygun dosyaları işaret eden dosyaları bintutan bir dizin oluşturmaktır ..bat.exe

DÜZENLEME 2: Ben Voigt'in başka bir yanıta yaptığı yorum, önerilen diğer ortam değişkenlerinin kullanılmasının %PATH%, depolanmadan önce genişletilecekleri için uzunluğunu azaltmayabileceğinden bahsediyor . Bu doğru olabilir ve bunun için test etmedim. Diğer bir seçenek ise, daha uzun dizin adları için 8dot3 formlarını kullanmaktır, örneğin C:\Program Filestipik olarak C:\PROGRA~1. Daha dir /xkısa isimleri görmek için kullanabilirsiniz .

DÜZENLEME 3: Bu basit test, Ben Voigt'in haklı olduğuna inanmamı sağlıyor.

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

Bunun sonunda, hellohelloyerine çıktı görüyorsunuz byehello.

DÜZENLEME 4: Toplu iş dosyalarını belirli yolları ortadan kaldırmak için kullanmaya karar verirseniz %PATH%, işlemin şeffaf olmasını sağlayacak şekilde, toplu iş dosyanızdan yürütülebilir dosyanıza bağımsız değişkenleri nasıl aktaracağınız konusunda endişeleriniz olabilir (yani, herhangi bir fark görmezsiniz) toplu iş dosyasının çağrılması ile yürütülebilir dosyanın çağrılması arasında). Toplu iş dosyaları yazma konusunda çok fazla deneyimim yok, ancak bu iyi çalışıyor gibi görünüyor.

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

Genel bir kural olarak, toplu iş dosyalarıyla sabit sürücünüzü biçimlendirmek gibi her türlü şeyi yapabileceğinizden, toplu iş dosyalarını internetten çalıştırırken dikkatli olmalısınız. Yukarıdaki koda (yazdığım) güvenmiyorsanız, satırı değiştirerek test edebilirsiniz.

%actualdir%\%actualfile% %args%

ile

echo %actualdir%\%actualfile% %args%

İdeal olarak, çalıştırmadan önce her satırın tam olarak ne yaptığını bilmelisiniz.


1
8dot3 formu iyi çalışıyor, ancak dizinler için çok büyük değil, örneğin "C: \ Program Files (x86) \ Microsoft Visual Studio 2008 SDK \ VisualStudioIntegration \ Tools \ Sandcastle \ ProductionTools \". Biraz tasarruf sağlayan başka bir şey de, bir kullanıcı olarak Sistem Yoluna dayalı bir PATH değişkeni oluşturabilmem ve başka bir Dir. Tüm bu yaklaşımlar "compact that string" türündedir, ancak Unix'te olduğu gibi merkezi bir ikili dosyalar dizinine sahip olabilir miyiz?
mjsr

1
Hmm, çok uzun dizinlerle ilgili olarak, tam tersinin doğru olduğunu düşünüyorum: dizin ne kadar uzun olursa, 8dot3 biçimini kullanarak o kadar çok karakter kaydedersiniz. İçeri girmek zorsa cmd, *yazmayı kaydetmek için kullanabileceğinizi unutmayın . Örneğin, kökten yazın dir /x pro*. İstediğiniz dizini 8dot3 adı ile birlikte göreceksiniz. Sonra cdona gitmek ve işlemi tekrarlamak için kullanın .
Mitch Schwartz

1
UNIX ile ilgili $PATHolarak %PATH%, Windows'dakine çok benzer şekilde çalışan bir cihazınız var , bu yüzden amacınızın tam olarak ne olduğundan emin değilim. Kural olarak, UNIX dizin adları Windows'dakinden daha kısa olma eğilimindedir ve sonuç olarak $PATHda daha kısa olma eğilimindedir.
Mitch Schwartz

2
Teşekkürler Mitch, sağladığınız Düzenleme 4 istediğim şeydi! Artık ihtiyacım olan tüm ikili dosyaları içeren merkezi bir klasöre sahip olabilirim. Bazı uygulamalarda bir sorun olup olmadığını görmek için daha derinlemesine test edeceğim
mjsr

2
Yürütülebilir dosyaya argümanları iletmek için 'edit 4' bölümünüz aşırı derecede karmaşık. Michael Burr'un cevabına bakın.
Dave Andersen

83

Bu,% PATH% ortam değişkeninizi ayrıştırır ve her dizini kısa ad eşdeğerine dönüştürür ve ardından hepsini bir araya getirir:

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

Çıkışı alın ve ortam değişkenlerinde PATH değişkenini güncelleyin.


Çok faydalı oldu teşekkürler !! Yolumu 1990'dan 1338'e kısalttı ve her şey hala bir cazibe gibi çalışıyor! Yaklaşımınızı seçtim çünkü her şeyi yolumda tutmak istedim ve toplu iş dosyaları üzerinden bağlantı kurmak çok zaman alıcı olurdu. TEŞEKKÜRLER!
ndrizza

2
Bu aynı zamanda yararlıydı çünkü bana zaman içinde biriken yolumdaki varolmayan tüm dizinlerden bahsetti.
Nate Glenn

27
Rapid Environment Editor, bunu yapmanın başka bir yoludur. Varolmayan dizinleri vurgular ve "uzun yolu kısaya dönüştür" seçeneğine sahiptir.
Russell Gallop

3
@RussellGallop: Bu, efendim, harika bir araç.
elo80ka

1
Sonrasında eksik kapanış teklifini not edin %%~sa. Cevabı güncellemeye çalıştım ama 6 karakteri değiştirmediğim sürece bana izin vermeyecek
zr870

28

windows vista veya üstünü kullanıyorsanız, klasöre sembolik bir bağlantı oluşturabilirsiniz. Örneğin:

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

bir bağlantı yapacak böylece c:\pfsizin olacaktır program filesklasörü. Bu numarayı kullanarak yolumdan 300 karakteri kestim.


Bu, kısmi bir yolu temsil etmek için bir ortam değişkeni kullanmaya güzel bir alternatiftir.
porcus

1
Bu kesinlikle daha yardımcı olacağını, ancak bir daha "doğru" (desteklenen?) Bir çözüm istiyorsanız, size örneklerini değiştirebilir c:\Program Filesve c:\Program Files (x86)önceden tanımlanmış değişkenler %ProgramFiles%ve %ProgramFiles(x86)% tenforums.com/tutorials/... Bunlar sadece birkaç karakterden tasarruf her , ancak GERÇEKTEN PATH'i maksimize etmenin eşiğindeyseniz, aradaki fark bu olabilir. Bu nedenle, doğru yollara çözümlenen% pf% ve% pfx% oluşturacağım. Fikir için teşekkürler! :)
rainabba

% Pf% ve% pfx% gibi değişkenleri kullanmakla ilgili sorun, sembolik bağlantılar oluşturmayla aynı sorunları yaşamanızdır - yazılım güncellemeleri yol değişkenine bir şeyler ekleyebilir. Bunun gibi değişkenleri kullanmanın diğer bir problemi de, etrafındaki şeyleri yazmanın veya onlara kaşiften göz atmanın hızlı ve kolay olmamasıdır. Açıkladığım yöntemi kullanarak c: \ PF'yi tam anlamıyla açabilirsiniz. Windows onu tıpkı bir klasör gibi görür, böylece ona da kolayca yarasa veya powershell yazabilirsiniz.
bmg002

10

Birinin ilgilenmesi durumunda ...

Tüm bu yollara bir seferde gerçekten ihtiyacım olmadığını anlıyorum, bu yüzden yolu buna göre değiştiren bir grup "başlatma" toplu iş dosyası oluşturuyorum.

Örneğin, Eclipse'de biraz C ++ geliştirme yapmak istersem, yapardım:

> initmingw
> initeclipse
> eclipse

Bu, aynı ada sahip yürütülebilir dosyalar (her ikisinde de make.exe bulunan C ++ ve D derleyicileri gibi) arasındaki çakışmaları önlemek için de kullanışlıdır.

Toplu iş dosyalarım genellikle şöyle görünür:

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

Bu yaklaşımı nispeten temiz buluyorum ve henüz herhangi bir sorunla karşılaşmadım.


7

Genelde bununla ilgili endişelenmeme gerek yok (yol boyutu sınırıyla karşılaşmadım - modern Windows sistemlerinde ne olduğunu bile bilmiyorum), ama işte bir programın dizinini koymaktan kaçınmak için yapabileceğim şey yol:

  • çoğu komut satırı yardımcı c:\utilprogramı yoldaki bir dizine atılır
  • aksi takdirde, c:\utilaşağıdaki gibi görünen dizine basit bir cmd / toplu iş dosyası ekleyeceğim :

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

temelde komut için bir takma ad oluşturur. Mutlaka mükemmel değil. Bazı programlar gerçekten yolda olmakta ısrar ediyor (bugünlerde bu oldukça nadirdir) ve onu çağırmaya çalışan diğer programlar onu doğru bulamayabilir. Ancak çoğu kullanım için iyi çalışıyor.

Ancak genel olarak, yola dizin eklemekten kaçınmak zorunda kalmadım.


Bu "yolu" izlemeye başladığınızda, bir toplu iş komut dosyasının "CALL [bat]" sözdizimi olmadan başka bir toplu komut dosyasını çağıramayacağına dikkat edin. Bu nedenle, yönlendirilmiş veya iletilmemiş exe'nizin bir yarasadan çağrıldığından emin olmak istiyorsanız, sadece "php script.php" yerine "php script.php'yi çağırın" kullanın (her iki şekilde de çalışır) Kullanmak için mükemmel bir neden. yarasa dağıtıcısı, PATH adlarının çakışmasını önlemektir (aynı exe'nin çoklu sürümü)
131

@ 131: 'Bu "yol" ile ne demek istediğini açıklayabilir misin? Örnekteki belirli dosya yolunu mu kastediyorsunuz? Yoksa bu cevabın önerdiği genel yöntem mi?
OR Mapper

@ORMapper: 131, 'Bu "yolu" izlemeye başladığınızda,' Bu tekniği kullandığınızda 'anlamına gelir.
Michael Burr

1
Sizin de yazdığınız gibi, "onu çağırmaya çalışan diğer programlar onu düzgün bulamayabilir" - duruma göre: Ne yazık ki, komut satırı uygulamalarına otomatik çağrılar, örneğin NAnt gibi araçların oluşturulması, tabii ki dışında. Bir çare, komutu başına bir ekleme ile çağırmaktır cmd /c, ancak bu da, derleme komut dosyasının Windows'a özgü olduğu anlamına gelir: / Bunu ayrı bir soruda sordum .
OR Mapper

5

Başka bir fikir: 8dot3 olmayan dosya adları için oluşturulan kısa adları belirlemek için DIR / X kullanın. Ardından bunları% PATH% yolunuzda kullanın.

Örneğin, 'C: \ Program Files', 'C: \ PROGRA ~ 1' olur.


1
Hata! Bunun @Mitch tarafından zaten önerildiğini fark ettim. Bunun için ona +1 vereceğim. :)
Android Eve


2

Her seferinde standart bir akış (stdin / stderr / stdout) ve çıkış kodu PROXY programı yazdım ve kullandım (dağıtıcı https://github.com/131/dispatcher olarak adlandırılır )

Kullandığım tüm CLI programları (node, php, python, git, svn, rsync, plink ...) aslında aynı exe dosyası (yaklaşık 10kb, sadece farklı isimlendirdiğim). dizin. Sahte bir statik açık metin dosyası, "proxy dosya adını gerçek exe eşlemesine" yapar.

Sevk görevlisi, kesinlikle şeffaf olması için düşük seviyeli Süreç yönetimi win32 API'sini kullanır.

Bu yazılımı kullandığımda, kullanabileceğim tüm programlar için PATH'ımda yalnızca BİR ek dizin ayarlıyım.


1

Yolunuza ekleyerek bir c: \ bin klasörü oluşturmak ve söylediğiniz gibi sabit bağlantı oluşturmak dizeyi kısaltabilir. Belki de sistem değişkenlerine c: \ Program Files değerine sahip bir pf değişkeni ekledikten sonra c: \ Program Files'ı path içinde% pf% ile değiştirin.

Düzenle:

Bir sanal sürücü oluşturun. subst p: "c: \ program dosyaları"


1
Yolun genişletilmiş değişkenleri içereceğini düşünüyorum, bu durumda kısalmayacaktır.
Ben Voigt

0

Girişleri yönetilebilir hale getirmek için şu adımları takip ediyorum:

  1. Yazılım paketlerinin farklı kullanım kombinasyonları için farklı kullanıcılar oluşturdu. Örnek: (a) Tüm web geliştirme yazılımlarını kullanıma sunmak için bir kullanıcı web sitesi oluşturuldu; (b) Tüm veritabanı ve veri ambarı yazılım paketlerini kullanılabilir hale getirmek için bir kullanıcı veritabanı oluşturdu. Bazı yazılımların birden fazla giriş oluşturabileceğini unutmayın. Veya bazen bunu oracle'a özgü ve MSSQL'e özgü ve oracle'a özgü kullanıcılara ayırıyorum. MySQL / PostgreSQL, tomcat, wamp, xamp hepsini webr kullanıcı hesabına koydum.

  2. Mümkünse ofis, photoshop, .. gibi ortak paketleri tüm kullanıcılar için sisteme özel olarak ve kullanıcıya özel özel paketler olarak kurun. Elbette farklı kullanıcılara giriş yapmam ve onları yüklemem gerekiyordu. Tüm yazılımlar bu seçeneği sunmayabilir. "Yalnızca bu kullanıcı için kur" seçeneği mevcut değilse, tüm sistem için kurun.

  3. Programları Program Dosyası (x86) klasörüne veya Program Dosyası'na yüklemekten kaçınıyorum. Ben her zaman temel dizine kurarım. Örneğin MySQL 64 bit "C: \ mysql64" ve MySQL 32 bit "C: \ mysql" klasörüne gider. Ben her zaman 64bit yazılım için 64 sonekini eklediğini varsayıyorum. Son ek yoksa, 32 bittir. Aynı şeyi Java ve diğerlerine de takip ediyorum. Bu şekilde yolum daha kısa olacak, "C: \ Program Dosyası (x86)" dahil değil. Bazı yazılımlar için, .exe dosyasının tam olarak nerede olduğunu göstermek için yapılandırma dosyasının düzenlenmesi gerekebilir. Yalnızca "C: \ Program Dosyası (x86)" içine yüklenmesini talep eden program bu klasöre yüklenecektir. Her zaman isimleri kısaltmayı hatırlıyorum. Tomcat / release / version-2.5.0.3 gibi sürüm numaralarından bu tür ayrıntılardan kaçınıyorum. Bilinen sürüme ihtiyacım olursa, Ad sürümüne göre bir dosya oluşturup tomcat klasörüne koyuyorum. Genel olarak bağlantıyı olabildiğince kısaltın.

  4. Yukarıdaki adımların tümü Windows sınırını geçtiyse, yolun kısaltılmış bağlantısını değiştirmek için herhangi bir toplu işi ekleyin.

Daha sonra kullanıma özel (mobil uygulama veya veritabanı / veri ambarlama veya web geliştirme .. ..) kullanıcıya giriş yapın ve ilgili görevleri yapın.

Ayrıca pencerelerin içinde sanal pencereler de oluşturabilirsiniz. Bir lisanslı işletim sistemi kopyanız olduğu sürece, aynı anahtarla birden çok sanal pencere oluşturmak mümkündür. O makinede belirli bir göreve özel paketler koyabilirsiniz. Her seferinde ayrı bir VM başlatmanız gerekir. 3D animasyon film yapımcıları gibi bellek yoğun paketlerin tümü ana makineye konulmalıdır, VM kullanımı için RAM'in yalnızca bir kısmına sahip olacağından VM'ye değil. Yine de her VM'yi başlatmak bir acıdır.


0

Yukarıdaki çözümler yalnızca yolunuzu kesebilirseniz işe yarar. Benim durumumda, bu gerçekten bir seçenek değildi ve bir komut istemini her açtığımda bir komut dosyası çalıştırmak zorunda olmak bir güçlüktü. Bu yüzden, komut istemini açarken otomatik olarak çalışan ve bir metin dosyasının içeriğini yolunuza ekleyen basit bir komut dosyası yazdım.

Bu betiğin çalıştırılmasının bazı şeyleri bozduğu (örneğin, bir github veya cygwin kabuğunda) bazı bağlamlar da vardır, bu yüzden, komut istemi içlerinde başlatılırsa, yol değişkeni isn olan yolların bir listesini içeren bir dosya da ekledim. Normalde yolu güncelleyen başlangıç ​​betiği aracılığıyla değiştirilmedi.

@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 şöyle görünecektir:

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 şeye benzeyecektir

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

Bunun başlangıçta otomatik olarak çalışmasını sağlamak için regedit'i açın, HKEY_LOCAL_MACHINE / SOFTWARE / Microsoft / Komut İşlemcisi'ne gidin, ardından sağda sağ tıklayın ve yeni -> Çoklu Dizgi Değeri'ne basın. AutoRun olarak adlandırın. Değeri olarak ayarlayın

C:\Users\Yams\setUpPath.bat

veya yukarıdaki toplu iş dosyasını sakladığınız başka bir yerde.


0

Denemedim, ancak PATH'i parçalara ayırmak işe yarayacak ve onları son değişken çalışmasında birleştirecek mi?

Örnek başlangıçta şöyle bir şeye sahip olduğunuzu varsayalım

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

Bunun yerine şunları yaratırsınız:

_PATH1 = {LONGPATH1};{LONGPATH2};....{2048 char}
_PATH2 = {2049th char}...{LONGPATH_N-1};{LONGPATH_N}
rem // may be more parts
PATH = %_PATH1%;%_PATH2%
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.