‘Pretty print’ windows% PATH% variable – como dividir em ‘;’ no shell CMD

Eu quero executar um simples one-liner no prompt do Windows CMD para imprimir minha variável %PATH% , uma input por linha.

Eu tentei isso: for /f "delims=;" %a in ("%path%") do echo %a for /f "delims=;" %a in ("%path%") do echo %a mas isso só imprime a primeira input:

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

Além disso, como você pode ver na saída acima, isso também está imprimindo o comando echo %a , bem como a saída. Há alguma maneira para parar isso?

Se eu tentar um comando similar, recebo todas as inputs, mas ainda assim obtenho a saída echo %a spamming dos resultados. Eu não entendo porque o seguinte imprime todas as inputs, mas minha tentativa em %PATH% não. Eu suspeito que eu não entendo o switch /F

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

A maneira mais simples é usar

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

Isso funciona para todos sem ; no caminho e sem " torno de um único elemento
Testado com path = C: \ qt \ 4.6.3 \ bin; C: \ Arquivos de Programas; C: \ documents & Settings

Mas uma solução “sempre” é um pouco complicada
EDIT: agora uma variante de trabalho

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

O que eu fiz lá?
Eu tentei resolver o problema principal: que os pontos-e-vírgulas dentro das aspas devem ser ignorados, e apenas os ponto e vírgula normais devem ser substituídos por ";"

Eu usei o próprio interpretador de lote para resolver isso para mim.

  • Primeiro eu tenho que fazer a corda segura , escapando de todos os caracteres especiais.
  • Então tudo ; são substituídos por ^;^;
  • e aí o truque começa com a linha
    set var=%var:"=""%" (A citação faltante é a chave!).
    Isso se expande de tal forma que todos os caracteres que escapingam perderão seu sinal de escape:
    var=foo & bar;;baz<>gak;;"semi^;^;colons^;^;^&embedded";;foo again!;;
    Mas apenas fora das cotações , agora há uma diferença entre ponto e vírgula fora das cotações ;; e dentro ^;^; .
    Essa é a chave.

Um simples liner para imprimir a variável de ambiente PATH :

 ECHO.%PATH:;= & ECHO.% 

Se o seu PATH foi igual a A;B;C a substituição da string acima irá mudar isto para ECHO.A & ECHO.B & ECHO.C e executará tudo de uma vez. O ponto final impede que as mensagens “ECHO está ligado” apareçam.

Eu tenho pequenas melhorias na inteligente “sempre” solução de jeb. Atualmente, a solução do jeb tem os seguintes problemas:

  1. Se o caminho inicial estiver entre aspas, a primeira saída começará com “”
  2. Se o caminho à direita estiver entre aspas, a última saída terminará com “”
  3. Se algum caminho contiver “” consecutivo inofensivo mas não funcional, a saída preserva o “”
  4. Se var contiver consecutivo ;; delimitadores então saídas ECHO está desligado

Esta solução corrige os problemas menores, além de usar menos 2 substituições. Também eliminei a repetida desnecessária ativação / desativação da expansão atrasada dentro do loop. (Editar em 2011-10-30 simplificou a lógica 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 ) 

Se você quiser ver uma linha em branco para cada caminho vazio resultante de consecutivos; delimitadores, a última linha do loop FOR pode simplesmente ler echo(%%~a vez disso.

Ou talvez seja mais óbvio exibir caminhos vazios como “” usando:
if %%a=="" (echo "") else echo %%~a

As várias correções de caminhos vazios funcionam também para a solução simples do jeb.

ATUALIZAÇÃO: Aqui está um simples one-liner usando o JREPL.BAT

Você pode usar meu utilitário de processamento de texto de expressão regular JREPL.BAT para obter uma solução simples e muito robusta. O JREPL.BAT é um script puro (JScript / batch híbrido) que é executado nativamente em qualquer máquina Windows do XP em diante.

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

Uma atualização para a solução inteligente de uma linha de Stephan Quan: O problema que encontrei foi que um ponto e vírgula à direita – (e talvez dois ponto e vírgula sucessivos, isto é, elemento de caminho vazio) faria com que a mensagem “ECHO está ligado” aparecesse. Eu resolvi isso, inserindo um período imediatamente após a segunda declaração ECHO (que é a syntax para suprimir ECHO é on / off mensagens). No entanto, isso resultará em uma linha extra vazia:

 ECHO %PATH:;= & ECHO.% 

Eu sei que isso é velho, mas FWIW; Eu sempre corro para querer isso por algum motivo ou outro. Algum tempo atrás, escrevi para mim mesmo um roteiro para fazer isso. Eu coloquei um pouco de polimento e postei no meu blog.

Sinta-se livre para usá-lo.

É chamado epath e o arquivo está em inzi.com. É compilado como um EXE para uso fácil (usando vbsedit): aqui

Você pode baixar o exe lá. Aqui está o código-fonte do script, se você quiser, como um script vbs.

  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 

A resposta de Stephen Quan é mais curta e melhor, mas aqui está uma solução Python:

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

Girando ; ponto e vírgula em \n novas linhas.

@ROMANIA_engineer propôs uma solução PowerShell em um comentário. Como a pergunta pede um comando que funcione no shell do CMD, aqui está uma maneira de usar esse código elegante do ambiente desejado do OP:

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

Para torná-lo ainda mais legível, você pode adicionar a sorting:

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

Crédito: https://stackoverflow.com/a/34920014/704808

Isso funciona na janela do cmd usando o Git Bash no Windows:

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

Você também pode criar um alias útil em seu .bash_profile :

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