"Pretty print" windows% PATH% variable - как разделить на; "; в оболочке CMD

Я хочу запустить простую одностроку в приглашении Windows CMD для печати моей переменной %PATH%, по одной записи в строке.

Я пробовал это: for /f "delims=;" %a in ("%path%") do echo %a, но это только печатает первую запись:

Z:\>for /f "delims=;" %a in ("%path%") do echo %a

Z:\>echo c:\python25\.
c:\python25\.

Также, как вы можете видеть из выведенного выше, это также печатает команду echo %a, а также вывод. Есть ли способ остановить это?

Если я попробую подобную команду, я получу все записи, но все равно получаю вывод echo %a для спама результатов. Я не понимаю, почему следующее печатает все записи, но моя попытка на %PATH% не работает. Я подозреваю, что не понимаю переключатель /F.

Z:\>for %a in (1 2 3) do echo %a

Z:\>echo 1
1

Z:\>echo 2
2

Z:\>echo 3
3

Ответ 1

Простым способом является использование

for %a in ("%path:;=";"%") do @echo %~a

Это работает для всех без ; в пути и без " вокруг одного элемента
Протестировано с помощью пути = C:\qt\4.6.3\bin; C:\Program Files; C:\documents & Settings

Но "всегда" решение немного сложнее
EDIT: Теперь рабочий вариант

@echo off
setlocal DisableDelayedExpansion
set "var=foo & bar;baz<>gak;"semi;colons;^&embedded";foo again!;throw (in) some (parentheses);"unmatched ;-)";(too"

set "var=%var:"=""%"
set "var=%var:^=^^%"
set "var=%var:&=^&%"
set "var=%var:|=^|%"
set "var=%var:<=^<%"
set "var=%var:>=^>%"

set "var=%var:;=^;^;%"
rem ** This is the key line, the missing quote is intended
set var=%var:""="%
set "var=%var:"=""%"

set "var=%var:;;="";""%"
set "var=%var:^;^;=;%"
set "var=%var:""="%"
set "var=%var:"=""%"
set "var=%var:"";""=";"%"
set "var=%var:"""="%"

setlocal EnableDelayedExpansion
for %%a in ("!var!") do (
    endlocal
    echo %%~a
    setlocal EnableDelayedExpansion
)

Что я там делал?
Я попытался решить основную проблему: точки с запятой внутри кавычек следует игнорировать, и только нормальные точки с запятой следует заменить на ";"

Я сам использовал пакетный интерпретатор, чтобы решить это для меня.

  • Сначала я должен сделать строку безопасной, избегая всех специальных символов.
  • Тогда все ; заменены на ^;^;
  • и тогда трюк начинается с линии
    set var=%var:"=""%" (Пропущенная цитата - ключ!).
    Это расширяется таким образом, что все экранированные символы теряют свой кадр:
    var=foo & bar;;baz<>gak;;"semi^;^;colons^;^;^&embedded";;foo again!;;...
    Но только вне кавычек, так что теперь существует разница между точками с запятой вне кавычек ;; и внутри ^;^; ,
    Это ключ.

Ответ 2

Простой один лайнер для печати типовой переменной PATH:

ECHO.%PATH:;= & ECHO.%

Если ваш PATH был равен A;B;C, приведенная выше замена строки изменит это на ECHO.A & ECHO.B & ECHO.C и выполнит все за один раз. Полная остановка предотвращает появление сообщений "ECHO on".

Ответ 3

Обновление для Stephan Quan очень умного решения с одним слоем: проблема, с которой я столкнулся, заключалась в том, что конечная полуточка - (и, возможно, два последовательных полуколония, то есть пустой элемент пути), вызовет сообщение "ECHO включено", появиться. Я решил это, вставив период сразу после второго оператора ECHO (который является синтаксисом для подавления сообщений ECHO вкл/выкл). Однако это приведет к дополнительной пустой строке:

ECHO %PATH:;= & ECHO.%

Ответ 4

У меня есть небольшие улучшения для умного "всегда" решения jeb. В настоящее время решение jeb имеет следующие проблемы:

  • Если ведущий путь заключен в кавычки, то первый вывод начинается с ""
  • Если конечный путь заключен в кавычки, то последний вывод заканчивается на ""
  • Если какой-либо путь содержит безвредные, но нефункциональные последовательные "", то выход сохраняет "
  • Если var содержит последовательные;; разделители затем выходят ECHO выключен

Это решение устраняет незначительные проблемы, плюс использует 2 замены. Также я устранил ненужное повторное включение/отключение задержки расширения в цикле. (Edit в 2011-10-30 упростил логику ENDLOCAL)

@echo off
setlocal DisableDelayedExpansion
set "var=%var:"=""%"
set "var=%var:^=^^%"
set "var=%var:&=^&%"
set "var=%var:|=^|%"
set "var=%var:<=^<%"
set "var=%var:>=^>%"
set "var=%var:;=^;^;%"
set var=%var:""="%
set "var=%var:"=""Q%"
set "var=%var:;;="S"S%"
set "var=%var:^;^;=;%"
set "var=%var:""="%"
setlocal EnableDelayedExpansion
set "var=!var:"Q=!"
for %%a in ("!var:"S"S=";"!") do (
  if "!!"=="" endlocal
  if %%a neq "" echo %%~a
)

Если вы хотите увидеть пустую строку для каждого пустого пути в результате последовательных;; разделителей, тогда последняя строка цикла FOR может просто читать echo(%%~a.

Или, возможно, было бы более очевидным отображать пустые пути как "", используя:
if %%a=="" (echo "") else echo %%~a

Различные пустые исправления пути работают и для простого решения jeb.


ОБНОВЛЕНИЕ. Ниже приведен простой простой лайнер с использованием JREPL.BAT

Вы можете использовать мою JREPL.BAT утилиту для регулярного выражения текста, чтобы получить простое, очень надежное решение. JREPL.BAT - это чистый script (гибридный JScript/пакет), который запускается изначально на любом компьютере Windows с XP и далее.

jrepl "([^;\q]+|\q.*?(\q|$))+" $0 /x /jmatch /s path

Ответ 5

Ответ Стивена Куана короче и лучше, но вот решение Python:

python -c "import os; print os.environ['PATH'].replace(';', '\n');"

Превращение ; с запятой в строки \n.

Ответ 6

Я знаю, что это старый, но FWIW; Я всегда сталкивался с этим по той или иной причине. Некоторое время назад я написал себе script для этого. Я положил немного польского на него и разместил его в своем блоге.

Не стесняйтесь использовать его.

Он называется epath, и файл находится на inzi.com. Он скомпилирован как EXE для удобства использования (используя vbsedit): здесь

Вы можете скачать exe там. Здесь исходный код для script, если вы хотите его как vbs script.

    scriptname = Wscript.ScriptName 'objFSO.GetFileName(WScript.FullName)

    Function BubbleSort(arrData,strSort)
    'borrowed from here: http://vbscripter.blogspot.com/2008/03/q-how-do-i-sort-data-in-array.html

    'Input: arrData = Array of data.  Text or numbers.
    'Input: strSort = Sort direction (ASC or ascending or DESC for descending)
    'Output: Array
    'Notes: Text comparison is CASE SENSITIVE
    '        strSort is checked for a match to ASC or DESC or else it defaults to Asc


        strSort = Trim(UCase(strSort))
        If Not strSort = "ASC" And Not strSort = "DESC" Then
            strSort = "ASC"
        End If 

        For i = LBound(arrData) to UBound(arrData)
          For j = LBound(arrData) to UBound(arrData)
            If j <> UBound(arrData) Then
                If strSort = "ASC" Then
                  If UCase(arrData(j)) > UCase(arrData(j + 1)) Then
                     TempValue = arrData(j + 1)
                     arrData(j + 1) = arrData(j)
                     arrData(j) = TempValue
                  End If
                End If

                If strSort = "DESC" Then
                    If UCase(arrData(j)) < UCase(arrData(j + 1)) Then
                        TempValue = arrData(j + 1)
                        arrData(j + 1) = arrData(j)
                        arrData(j) = TempValue
                     End If        
                End If 
            End If
          Next
        Next

        BubbleSort = arrData

    End Function

    If Wscript.Arguments.Count>0 Then

        Set args = Wscript.Arguments

        bInLines = False
        bInAlphabetical = False
        bReverseSort = False
        bShowHelp = False

        For Each arg In args
            Select Case arg
                Case "-l"
                    bInLines = True
                Case "-a"
                    bInAlphabetical = True
                Case "-r"
                    bReverseSort = True
                Case Else
                    bShowHelp=True
            End Select  

        Next

        If bInLines = False Then
            bShowHelp=True
        End if

        If bShowHelp Then

                    sTxt = sTxt + "" & vbCrLf
                    sTxt = sTxt +  scriptname  & " Displays the system path in optionally friendly formats." & vbCrLf
                    sTxt = sTxt +  "ePath is helpful when viewing the system path and easily identifying folders therein." & vbCrLf
                    sTxt = sTxt + "" & vbCrLf
                    sTxt = sTxt + "EPATH [-l] [-a] [-r]" & vbCrLf
                    sTxt = sTxt + "" & vbCrLf
                    sTxt = sTxt + "Switches:" & vbCrLf
                    sTxt = sTxt + vbTab + "[-l]" + vbtab + "Show the path broken out in lines" & vbCrLf
                    sTxt = sTxt + vbtab + "[-a]" + vbTab + "Sort the path broken out in lines sorted alphabetically" & vbCrLf
                    sTxt = sTxt + vbtab + "[-r]" + vbTab + "Reverse the alphabetic sort [asc default] (ignored without -a)" & vbCrLf
                    sTxt = sTxt + "" & vbCrLf
                    sTxt = sTxt + vbTab + "Examples:" & vbCrLf
                    sTxt = sTxt +  vbTab + vbTab + scriptname  & vbTab & "(Show %PATH% normally)" & vbCrLf
                    sTxt = sTxt +  vbTab + vbTab + scriptname  & " -l" & vbCrLf
                    sTxt = sTxt +  vbTab + vbTab + scriptname  & " -l -a" & vbCrLf
                    sTxt = sTxt +  vbTab + vbTab + scriptname  & " -l -a -r" & vbCrLf
                    sTxt = sTxt +  vbTab + vbTab + scriptname  & " -? Display help (what you are seeing now)" & vbCrLf
                    sTxt = sTxt + "" & vbCrLf
                    sTxt = sTxt + "More info or questions at http://inzi.com" & vbCrLf


                    Wscript.Echo sTxt

                    WScript.Quit

        Else
            Set wshShell = CreateObject( "WScript.Shell" )
            sPath = wshShell.ExpandEnvironmentStrings( "%PATH%" )
            thePath = Split(sPath,";")

            If bInAlphabetical Then
                If bReverseSort Then
                    sDirection = "DESC"
                End If

                thePath = BubbleSort(thePath, sDirection)
            End if


            For Each item In thePath
                WScript.Echo item
            Next
            Set wshShell = Nothing
        End if
    Else
        'Nothing, echo the path.

        Set wshShell = CreateObject( "WScript.Shell" )
        WScript.Echo wshShell.ExpandEnvironmentStrings( "%PATH%" )
        Set wshShell = Nothing

    End If

Ответ 7

@ROMANIA_engineer предложил решение PowerShell в комментарии. Поскольку вопрос запрашивает команду, которая работает в оболочке CMD, вот способ использовать этот элегантный код из желаемой среды OP:

powershell -Command ($env:Path).split(';')

Чтобы сделать его еще более читаемым, вы можете добавить сортировку:

powershell -Command ($env:Path).split(';') | sort

Кредит: fooobar.com/questions/28821/...

Ответ 8

Это работает в окне cmd с помощью Git Bash в Windows:

echo -e ${PATH//:/\\n}

Вы также можете сделать удобный псевдоним в своем .bash_profile:

alias showpath='echo -e ${PATH//:/\\n}'

Ответ 9

Этот скрипт будет анализировать текущий путь Windows в TXT файл, используя JREPL.bat. Это было вдохновлено вышеупомянутым сообщением dbenham.

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

:::: THIS SCRIPT WILL PARSE THE CURRENT WINDOWS PATH INTO AT TXT FILE ::::
:::: EACH FOLDER FOUND IN PATH WILL BE ON A SEPARATE LINE ::::

:::: SCRIPT INSTRUCTIONS ::::
:: PLACE JREPL.bat IN C:\WINDOWS\SYSTEM32 FOLDER OR CUSTOM LOCATION OF YOUR CHOOSING ::
:: IF PLACED IN CUSTOM FOLDER YOU MUST LINK IT TO WINDOWS PATH ::
:: YOU CAN ACCESS WINDOWS PATH BY RUNNING THE BELOW COMMAND IN CMD.EXE ::
:: Rundll32 sysdm.cpl,EditEnvironmentVariables ::
:: DOWNLOAD JREPL.bat https://www.dostips.com/forum/viewtopic.php?t=6044 ::

:: SET WORKING DIRECTORY ::
CD /D "C:\WINDOWS\SYSTEM32"

:: UNCOMMENT LINE BELOW AND SET YOUR JREPL.bat SAVED FOLDER PATH IF YOU HAVE A BACKUP COPY ::
:: SET JOUT=<FOLDER PATH>

:: SET OUTPUT FILE ::
    SET FOUT=%USERPROFILE%\DESKTOP\PARSE.TXT

:: SET FILE TO SEARCH FOR ::
:: THIS SEARCHES FOR JREPL.BAT IN THE CURRENT WORKING DIR ::
    SET I=JREPL.BAT

:: SET CONTROL FILE TO CHECK AGAINST ::
:: THIS IS FOR DEBUGGING PURPOSES AND SHOULD NOT BE CHANGED OTHERWISE ::
    SET J=JREPL.BAT

:::: START SCRIPT ::::
    SET RESULT=
    FOR /F "DELIMS=" %%A IN ('DIR /B /O:N ^| FINDSTR /S /I "%I%" %TMP_RESULT_FILE%') DO (
    SET RESULT=%%A
    )

IF /I !RESULT! EQU %J% (
ECHO !RESULT! ^^!^^!EXISTS^^!^^!
    TIMEOUT 3 >NUL
    CALL :FOUND
    GOTO END
) ELSE (
    GOTO NOTFOUND
)
    GOTO ERROR

:FOUND
    FOR %%G IN (%I%) DO (
    %%G "([^;\Q]+|\Q.*?(\Q|$))+" $0 /X /JMATCH /S PATH>>%FOUT%
    CLS && ECHO.
ECHO %I% ^^!^^!EXECUTED SUCCESSFULLY^^!^^!
    TIMEOUT /T 3 >NUL
    EXPLORER "%FOUT%"
    GOTO END
( ELSE )
    GOTO ERROR
)

:NOTFOUND
    ECHO %I% ^^!^^!NOT FOUND^^!^^!
    TIMEOUT 3 >NUL
    CLS && ECHO.
:: UNCOMMENT THE LINES BELOW TO OPEN JREPL.BAT SAVE FOLDER IF AVAILABLE ::
    :: ECHO ^^!^^!OPENING^^!^^! %I% SAVED FOLDER
  :: TIMEOUT 3 >NUL
    :: EXPLORER "%JOUT%"
  GOTO END
    ( ELSE )
    GOTO ERROR
    )

:ERROR
    CLS && ECHO.
    ECHO ^^!^^!ERROR RUNNING^^!^^! %I%
    TIMEOUT 3 >NUL
    CLS && ECHO.
    ECHO ^^!^^!PLEASE FIX SCRIPT^^!^^! ::::::::::::::::::
    TIMEOUT 3 >NUL

:END
    ENDLOCAL && EXIT /B