Spacje i nawiasy w systemie Windows Zmienna PATH psuje pliki wsadowe


14

Zatem moja zmienna ścieżki (System-> Ustawienia Adv-> Env Vars-> System-> PATH) jest ustawiona na:

C:\Python26\Lib\site-packages\PyQt4\bin;
%SystemRoot%\system32;
%SystemRoot%;
%SystemRoot%\System32\Wbem;
%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;
C:\Python26\;
C:\Python26\Scripts\;
C:\cygwin\bin;
"C:\PathWithSpaces\What_is_this_bullshit";
"C:\PathWithSpaces 1.5\What_is_this_bullshit_1.5";
"C:\PathWithSpaces (2.0)\What_is_this_bullshit_2.0";
"C:\Program Files (x86)\IronPython 2.6";
"C:\Program Files (x86)\Subversion\bin";
"C:\Program Files (x86)\Git\cmd";
"C:\Program Files (x86)\PuTTY";
"C:\Program Files (x86)\Mercurial";
Z:\droid\android-sdk-windows\tools;

Chociaż oczywiście bez nowych linii.

Zwróć uwagę na wiersze zawierające PathWithSpaces- pierwszy nie ma spacji, drugi ma spację, a trzeci ma spację, po której następuje nawias.

Teraz zwróć uwagę na wynik tego pliku wsadowego:

C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\>vcvars32.bat
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin>"C:\Program Files (x86
)\Microsoft Visual Studio 9.0\Common7\Tools\vsvars32.bat"
Setting environment for using Microsoft Visual Studio 2008 x86 tools.
\What_is_this_bullshit_2.0";"C:\Program was unexpected at this time.
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin>      set "PATH=C:\Pro
gram Files\Microsoft SDKs\Windows\v6.0A\bin;C:\Python26\Lib\site-packages\PyQt4\
bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\
WindowsPowerShell\v1.0\;C:\Python26\;C:\Python26\Scripts\;C:\cygwin\bin;"C:\Path
WithSpaces\What_is_this_bullshit";"C:\PathWithSpaces 1.5\What_is_this_bullshit_1
.5";"C:\PathWithSpaces (2.0)\What_is_this_bullshit_2.0";"C:\Program Files (x86)\
IronPython 2.6";"C:\Program Files (x86)\Subversion\bin";"C:\Program Files (x86)\
Git\cmd";"C:\Program Files (x86)\PuTTY";"C:\Program Files (x86)\Mercurial";Z:\dr
oid\android-sdk-windows\tools;"

lub konkretnie wiersz:

\What_is_this_bullshit_2.0";"C:\Program was unexpected at this time.

Więc co to za bzdury?

Konkretnie:

  • Katalog w ścieżce, który jest poprawnie poprzedzony cudzysłowami, ale bez spacji = dobrze
  • Katalog w ścieżce, który jest poprawnie poprzedzony cudzysłowami i ma spacje, ale bez nawiasów = w porządku
  • Katalog w ścieżce, który jest poprawnie poprzedzony cudzysłowami, ma spacje i ma nawias = BŁĄD

Co tu się dzieje? Jak mogę to naprawić? Prawdopodobnie skorzystam z punktu połączenia, aby moje narzędzia nadal działały jako obejście, ale jeśli masz wgląd w to, daj mi znać :)


W oparciu o moje rozumienie omawianych problemów powyższa odpowiedź jest poprawna i polega na wzięciu pod uwagę, że polecenie SET jest poleceniem, a PATH jest częścią jego argumentu, którego równowaga stanowi nowy ciąg PATH. Tak więc, IMO, nie chodzi o to, że jest to mało udokumentowane, ale o to, że jest raczej niejasnym przypadkiem na krawędzi. Właśnie spędziłem kilka godzin na tym problemie.
David A. Gray,

Odpowiedzi:


13

Może się to zdarzyć, jeśli w wierszu wewnątrz „bloku” znajdują się nieskalowane nawiasy (które również używają nawiasów do rozgraniczenia).

Zwykle można to naprawić, włączając opóźnione rozszerzanie i używając zmiennych !var!zamiast %var%. Nie ma o wiele więcej rad, których mógłbym udzielić, nie widząc kodu.



13

W zmiennej środowiskowej PATH MS-Windows nie powinno być żadnych (a) cudzysłowów (polecenie PATH) ani (b) cudzysłowu otaczającego całe wyrażenie po poleceniu (SET) . Niestety nie jest to dobrze udokumentowane przez MS, chociaż stwierdzają, że jeśli używane są cudzysłowy, zostaną one uwzględnione w wartości zmiennej (Windows XP Command Line Reference) .

$ SET BLAH="blah blah(1)"
$ ECHO %BLAH%
"blah blah(1)"
$ SET BLAH=blah blah(1)
$ ECHO %BLAH%
blah blah(1)

Może to powodować problemy, które są niespójne, a zatem trudne do zdiagnozowania. Na przykład, jeśli ścieżka zawiera „C: \ Python27”, twój komputer powie „python” nie jest rozpoznawany jako polecenie wewnętrzne lub zewnętrzne, program operacyjny lub plik wsadowy. ” podczas próby uruchomienia Pythona. Jednak niektóre biblioteki mogą być nadal dostępne.

Zdajesz nie trzeba „Escape” spacji i nawiasów. Jeśli potrzebujesz znaków specjalnych, wstaw cudzysłowy wokół całego wyrażenia, w tym nazwy zmiennej.

SET "PATH=%PATH%;C:\Program Files (x86)\path with special characters"

Możesz też użyć nawiasów.

(SET VAR=can't contain ampersand, parentheses, pipe, gt or lt)

Uwaga: podwójne cudzysłowy muszą występować parami.

(SET VAR=illegal characters!@#$%^*_-+={}[]\:;""',./?)
echo %VAR%
illegal characters!@#$%*_-+={}[]\:;""',./?

Jednak prawdopodobnie nie ma żadnych poprawnych nazw ścieżek, które mogłyby spowodować problem z poleceniem SET.



1
Napisałeś MS-DOS, gdy miałeś na myśli MS-Windows, a twoje polecenia były dla MS-Windows. OP zapytał o MS-Windows. Więc dlaczego nazywacie to MS-DOS, nie wiem. Nawet twoje linki mówiły NT (To znaczy - Windows. Kiedyś było 9X i NT, teraz jest to po prostu NT). Windows i MS-DOS to dwa różne systemy operacyjne. Widziałem wcześniej wiersz poleceń systemu Windows błędnie nazywany DOS, ale nawet to nie jest tak złe, jak to, co nazwałeś.
barlop

@barlop, oczywiście, że masz rację. Dzięki za zmiany. Do Windows-95 Windows był aplikacją zbudowaną na DOS. Możesz uruchomić system Windows, wpisując winpolecenie w systemie DOS. W rzeczywistości przed Windows-3.1 wszystko, takie jak Zork i WordStar, było aplikacjami DOS. Potem, począwszy od Windows-98, nie było DOS-a. Ale myślę, że niektóre stare timery, takie jak ja, nadal błędnie odnoszą się do powłoki CMD jako powłoki DOS. Przepraszam za zamieszanie i jeszcze raz dziękuję za wyjaśnienie intencji mojej odpowiedzi.
Mark Mikofski

@MarkMikofski Właściwie system Windows 9X (95/98 / ME) został prawdopodobnie zbudowany również na systemie DOS. Możesz na przykład edytować jakiś plik (może msdos.sys) niektóre opcje, takie jak bootGUI = 0, i zatrzymać ładowanie systemu Windows tokyopc.org/newsletter/1996/08/msdosed.html Czy możesz wtedy załadować okna stamtąd nie wiem. Dysk rozruchowy Win9X jest uważany za DOS. Stare liczniki czasu, które wiedzą, o czym mówią, tak jak ty, zwykle są ostatnimi osobami, które popełniły błąd, nazywając wiersz poleceń systemu Windows DOS. I są pierwszymi ludźmi, którzy są najbardziej nieugięci, że to nie DOS.
barlop

1
Czy próbowałeś poradzić (SET PATH=%PATH%;C:\Program Files (x86)\path with special characters)? Zupełnie źle!
JosefZ,

2

Microsoft dokumentuje problem w „ Błąd uruchamiania skryptów powłoki poleceń zawierających nawiasy ”.

Sugerowane przez nich rozwiązanie polega na zastosowaniu opóźnionego rozszerzenia.

SETLOCAL ENABLEDELAYEDEXPANSION
SET VAR=string containing ( and ) ...
IF "y" == "y" (
    ECHO !VAR! %VAR%
)
ENDLOCAL

Aby ustawić ścieżkę w bloku if, zamiast używać SET PATH=, prawdopodobnie powinieneś użyć PATHpolecenia.

SET AddToPath=C:\Program Files (x86)\Whatever

SETLOCAL ENABLEDELAYEDEXPANSION
IF "%X%" == "%Y%" (
    ECHO Adding !AddToPath! to path !PATH!
    PATH !AddToPath!;!PATH!
)

W przypadku innych zmiennych innym rozwiązaniem może być użycie cudzysłowów, ale ogólnie:

SET "MyVar=C:\Program Files (x86)\Whatever"

1

Joey w swojej odpowiedzi mówi

Może się to zdarzyć, jeśli w wierszu wewnątrz „bloku” znajdują się nieskalowane nawiasy (które również używają nawiasów do rozgraniczenia).

i to prawda. Jeśli są nawiasy nieskalowane, należy je uniknąć. To jest to co zrobiłem; Wymieniłem

set PATH=some_path;%PATH%

z

set PATH="some_path;%PATH%"

i to rozwiązało problem.


2
Nie. Powinieneś użyćset "PATH=some_path;%PATH%"
JosefZ,

1

Doświadczyłem czegoś podobnego. Microsoft wyjaśnia problem tutaj: http://support.microsoft.com/kb/329308

Zasadniczo, zamiast zmieniać zmienną Path za pomocą System-> Adv Settings-> Env Vars-> System-> PATH, spróbuj

My Computer->Manage->Computer Management (local)-> Properties-> Advanced-> Environment variables-> Settings

1

W systemie Windows 8 nie udało mi się osiągnąć sukcesu przy żadnej z tych metod. Nawiasy nie działają, cytaty działają, ale „ścieżka”, którą modyfikujesz w ten sposób, nie jest ścieżką używaną do lokalizowania plików wykonywalnych, zamiast tego cmdnadal wydaje się, że używa ścieżki systemowej odziedziczonej po otwarciu okna.

przykład: po określeniu architektury procesora chcę dodać kilka ścieżek do zmiennej środowiskowej PATH. Właściwie nawet dodanie ich tymczasowo działałoby, ponieważ potrzebuję ich tylko podczas działania pliku wsadowego. Ale to nawet nie działa.

echo %path%wyświetla PATH systemowy w momencie cmduruchomienia.

set path="%path%;%programfiles(x86)%\company\program\subdir"działa, ale teraz %path%zawiera wszystko otoczone cudzysłowami, a jeśli spróbuję uruchomić program w podkatalogu z innego miejsca, nie powiedzie się. Używanie nawiasów wokół całego tekstu zamiast cudzysłowów nie działa .

Zauważyłem też, że to samo polecenie będzie działać, jeśli zostanie wprowadzone interaktywnie cmd, ale nie, jeśli zostanie napotkane w pliku wsadowym. To przerażające. Kolejną osobliwością jest przerywana utrata ostatniego znaku wartości zmiennej środowiskowej! Inna niespójność dotyczy programów innych firm: niektóre mogą obsługiwać %var%parametr jako parametr, inne nie.


1

Miałem ogromne problemy z wykonaniem poniższej pracy w Win8, dopóki nie dodałem podwójnych cudzysłowów wokół wartości, którą ustawiałem dla zmiennej fromFile. Bez tego, gdy fromFile zawierał nazwę pliku z nawiasami, następny wiersz, który próbował dokonać podstawienia łańcucha w celu wygenerowania zmiennej toFile, zawiódł. Zauważ, że używam tam rozwiniętego opóźnienia do oceny zmiennej w czasie wykonywania zamiast w czasie analizy (odpowiedniej instancji CALL)

::-- BATCH file that creates an *_576_5.* file from an *_640_t.* one (copying it)
::-- Author: George Birbilis (http://zoomicon.com)
::-- Credits: String replacement based on http://www.dostips.com/DtTipsStringManipulation.php

@ECHO OFF

::-- Loop for all files recursively --::

FOR /R %%f in (*_640_t.*) DO CALL :process %%f

ECHO(
PAUSE

GOTO :EOF

::-- Per-file actions --::

:process

:: Display progress...
::ECHO Processing %*
<nul (set/p dummy=.)

SETLOCAL ENABLEDELAYEDEXPANSION
SET fromFile="%*"
SET toFile=!fromFile:_640_t=_576_t!

IF NOT EXIST %toFile% CALL :generate %fromFile% %toFile%

GOTO :EOF

::-- Generate missing file --::

:generate

ECHO(
ECHO COPY %*
COPY %*

::PAUSE

GOTO :EOF
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.