'Pretty print' windows %PATH% variable - how to split on ';' in CMD shell

WindowsBatch FileCmdPath

Windows Problem Overview


I want to run a simple one-liner in the Windows CMD prompt to print my %PATH% variable, one entry per line.

I tried this: for /f "delims=;" %a in ("%path%") do echo %a but this only prints the first entry:

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

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

Also as you can see from the output above, this is also printing the echo %a command as well as the output. Is there any way to stop this?

If I try a similar command, I get all the entries, but still get the echo %a output spamming the results. I don't understand why the following prints all entries, but my attempt on %PATH% doesn't. I suspect I don't understand the /F switch.

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

Z:\>echo 1
1

Z:\>echo 2
2

Z:\>echo 3
3

Windows Solutions


Solution 1 - Windows

The simple way is to use

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

This works for all without ; in the path and without " around a single element
Tested with path=C:\qt\4.6.3\bin;C:\Program Files;C:\documents & Settings

But a "always" solution is a bit complicated
EDIT: Now a working variant

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

What did I do there?
I tried to solve the main problem: that the semicolons inside of quotes should be ignored, and only the normal semicolons should be replaced with ";"

I used the batch interpreter itself to solve this for me.

  • First I have to make the string safe, escaping all special characters.
  • Then all ; are replaced with ^;^;
  • and then the trick begins with the line
    set var=%var:"=""%" (The missing quote is the key!).
    This expands in a way such that all escaped characters will lose their escape caret:
    var=foo & bar;;baz<>gak;;"semi^;^;colons^;^;^&embedded";;foo again!;;...
    But only outside of the quotes, so now there is a difference between semicolons outside of quotes ;; and inside ^;^;.
    Thats the key.

Solution 2 - Windows

A simple one liner to prettying printing the PATH environment variable:

ECHO.%PATH:;= & ECHO.%

If your PATH was equal to A;B;C the above string substitution will change this to ECHO.A & ECHO.B & ECHO.C and execute it all in one go. The full stop prevents the "ECHO is on" messages from appearing.

Solution 3 - Windows

An update to Stephan Quan's very clever one-liner solution: The problem I encountered was that a trailing semi-colon - (and maybe two successive semi-colons, i.e. empty path element) would cause the message "ECHO is on" to appear. I solved this by inserting a period immediately after the second ECHO statement (which is the syntax to suppress ECHO is on/off messages). However, it will result in an extra empty line:

ECHO %PATH:;= & ECHO.%

Solution 4 - Windows

I have minor improvements to jeb's clever "always" solution. Currently jeb's solution has the following issues:

  1. If the leading path is enclosed in quotes, then the first output starts with ""

  2. If the trailing path is enclosed in quotes, then the last output ends with ""

  3. If any path contains harmless but non-functional consecutive "", then the output preserves the ""

  4. If var contains consecutive ;; delimiters then outputs ECHO is off

This solution fixes the minor issues, plus it uses 2 fewer substitutions. Also I eliminated the unnecessary repeated enabling/disabling delayed expansion within the loop. (Edit on 2011-10-30 simplified the ENDLOCAL logic)

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

If you want to see a blank line for each empty path resulting from consecutive ;; delimiters, then the last line of the FOR loop can simply read echo(%%~a instead.

Or perhaps it would be more obvious to display empty paths as "" using:
if %%a=="" (echo "") else echo %%~a

The various empty path fixes work for jeb's simple solution as well.


UPDATE: Here is a simple one-liner using JREPL.BAT

You can use my JREPL.BAT regular expression text processing utility to achieve a simple, very robust solution. JREPL.BAT is pure script (hybrid JScript/batch) that runs natively on any Windows machine from XP onward.

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

Solution 5 - Windows

This works in cmd window using Git Bash on Windows:

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

You can also make a handy alias in your .bash_profile:

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

Solution 6 - Windows

Stephen Quan's answer is shorter and better, but here's a Python solution:

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

Turning ; semicolons into \n newlines.

Solution 7 - Windows

@ROMANIA_engineer proposed a PowerShell solution in a comment. Since the question asks for a command that works in the CMD shell, here is a way to use that elegant code from the OP's desired environment:

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

To make it still more readable, you can add sorting:

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

Credit: https://stackoverflow.com/a/34920014/704808

Solution 8 - Windows

I know this is old, but FWIW; I always run into wanting this for some reason or another. Some time ago, I wrote myself a script to do this. I put a little polish on it and posted it on my blog.

Feel free to use it.

It's called epath, and the file is at inzi.com. It's compiled as an EXE for easy use (using vbsedit): here

You can download the exe there. Here's the source code to the script if you want it as a 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

Solution 9 - Windows

Here is a well commented script that parses a semicolon-separated list of items, regarding optional quotation of each item and allowing even items with semicolons in them (when quoted). Since it utilises a goto loop it might not be the fastest approach though, but it should be safe against special characters:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define semicolon-separated list here (sample taken from https://stackoverflow.com/a/5472168):
set "BUFFER=foo & bar;baz<>gak;"semi;colons;^&embedded";foo again!;throw (in) some (parentheses);"unmatched ;-)";(too"

setlocal EnableDelayedExpansion
echo BUFFER: !BUFFER!
echo/
endlocal

rem // Initialise items counter and clear (pseudo-)array variable:
set /A "IDX=0" & for /F "delims==" %%V in ('set $ITEM[ 2^> nul') do set "%%V="
rem // Utilise a `goto` loop to retrieve all items:
:PARSE_LOOP
rem // Check for availability of further items:
if defined BUFFER (
    rem // Increment items counter:
    set /A "IDX+=1"
    rem // Toggle delayed expansion to avoid troubles with `!`:
    setlocal EnableDelayedExpansion
    rem // Put current items counter into a `for` meta-variable:
    for %%I in (!IDX!) do (
        rem // Check whether current item begins with `"`, hence it is quoted:
        if "!BUFFER:~,1!" == ""^" (
            rem /* This point is reached when current item is quoted, hence
            rem    remove the opening `"` and split off everything past the
            rem    next one (that is the closing `"`) from the items buffer: */
            for /F tokens^=1*^ delims^=^"^ eol^=^" %%A in (";!BUFFER:~1!") do (
                endlocal
                rem // Store current item into array in unquoted manner:
                set "$ITEM[%%I]=%%A" & setlocal EnableDelayedExpansion
                for /F "delims=" %%C in ("$ITEM[%%I]=!$ITEM[%%I]:~1!") do (
                    endlocal & set "%%C" & if not defined $ITEM[%%I] set /A "IDX-=1"
                )
                rem /* Transfer remaining items beyond `endlocal` barrier;
                rem    note that a delimiters-only line still causes `for /F`
                rem    to iterate when there is just `tokens=*`: */
                for /F "tokens=* delims=;" %%D in (";%%B") do set "BUFFER=%%D"
                setlocal EnableDelayedExpansion
            )
        ) else (
            rem /* This point is reached when current item is not quoted,
            rem    hence split items string at next semicolon `;`: */
            for /F "tokens=1* delims=;" %%A in ("!BUFFER!") do (
                endlocal
                rem // Store current (unquoted) item into array:
                set "$ITEM[%%I]=%%A"
                rem // Transfer remaining items beyond `endlocal` barrier:
                set "BUFFER=%%B"
                setlocal EnableDelayedExpansion
            )
        )
    )
    endlocal
    rem // Loop back to retrieve next item:
    goto :PARSE_LOOP
)
rem // Return all retrieved items:
setlocal EnableDelayedExpansion
for /L %%I in (1,1,%IDX%) do echo ITEM %%I: !$ITEM[%%I]!
endlocal

echo/
echo INFO:   %IDX% items
echo ERROR:  %ErrorLevel%

endlocal
exit /B

Solution 10 - Windows

Original Version

This is an approach that only performs several character substitutions, which can properly handle a semicolon-separated list of optionally quoted items, which, when quoted, may even contain semicolons on their own. Empty list items are also dealt with correctly. The key to success is to become able to distinguish between semicolons within quotes (which are part of a list item) and those not (which constitute the separators):

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define semicolon-separated list here (sample taken from https://stackoverflow.com/a/5472168):
set "BUFFER=foo & bar;baz<>gak;"semi;colons;^&embedded";foo again!;throw (in) some (parentheses);"unmatched ;-)";(too"
rem set "BUFFER="caret ^^";"bang !";"caret ^^ bang !""

set BUFFER & echo/

setlocal EnableDelayedExpansion
rem // Replace `^` by `^@` to avoid sequences of `^`:
set "BUFFER=!BUFFER:^=^@!"

rem // Escape special characters `^`, `&`, `<`, `>`, `|`:
set "BUFFER=!BUFFER:^=^^!"
set "BUFFER=!BUFFER:&=^&!"
set "BUFFER=!BUFFER:<=^<!"
set "BUFFER=!BUFFER:>=^>!"
set "BUFFER=!BUFFER:|=^|!"

rem // Escape `;`:
set "BUFFER=!BUFFER:;=^;!"

rem // Expand immediately, so escaping is processed for unquoted portions:
endlocal & set ^"BUFFER=%BUFFER%^"
setlocal EnableDelayedExpansion

rem // Escape `^`, `&`, `<`, `>`, `|`, hence quoted portions become double-escaped:
set "BUFFER=!BUFFER:^=^^!"
set "BUFFER=!BUFFER:&=^&!"
set "BUFFER=!BUFFER:<=^<!"
set "BUFFER=!BUFFER:>=^>!"
set "BUFFER=!BUFFER:|=^|!"

rem /* Replace `^^^` by `^` in order to resolve double-escaping;
rem    at this point, quoted `;` are represented by the sequence `^^;`: */
set "BUFFER=!BUFFER:^^^=^!"

rem // Escape `"`, so everything appears unquoted then:
set "BUFFER=!BUFFER:"=^^"!"

rem /* Expand immediately, so escaping is again processed;
rem    at this point, originally quoted `;` are represented by `^;`: */
set "BUFFER=!BUFFER:^=^^^!"
set ^"BUFFER=%BUFFER:!=^^!%^" !

rem // Remove all `"` from string:
set "BUFFER=!BUFFER:"=!^"

rem // Enclose whole string in `""` and replace each `;` by `";"`:
set ^"BUFFER="!BUFFER:;=";"!"^"

rem // Replace `^";"` (which are originally quoted `;`) by `;`:
set "BUFFER=!BUFFER:^";"=;!"

rem // Finally revert initial replacement of `^` by `^@`:
set "BUFFER=!BUFFER:^@=^!"

set BUFFER & echo/

rem // Eventually return the list items:
for %%I in (!BUFFER!) do (
    if "!!"=="" endlocal & rem // (technique taken from https://stackoverflow.com/a/7940444)
    echo(%%~I
)

endlocal
exit /B

Improved Version

Here is an improved approach that performs less substitutions:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define semicolon-separated list here:
set "BUFFER="caret ^^";"bang !";"caret ^^; ^& bang !";caret ^;bang !;caret ^@ & bang !"

set BUFFER & echo/

setlocal EnableDelayedExpansion
rem // Replace `^` by `^@` to avoid sequences of `^`:
set "BUFFER=!BUFFER:^=^@!"

rem // Double-escape special characters `^`, `&`, `<`, `>`, `|`:
set "BUFFER=!BUFFER:^=^^^^!"
set "BUFFER=!BUFFER:&=^^^&!"
set "BUFFER=!BUFFER:<=^^^<!"
set "BUFFER=!BUFFER:>=^^^>!"
set "BUFFER=!BUFFER:|=^^^|!"

rem // Replace `;` by `^^;`:
set "BUFFER=!BUFFER:;=^^;!"

rem // Expand immediately, so escaping is processed for unquoted portions:
endlocal & set ^"BUFFER=%BUFFER%^"
setlocal EnableDelayedExpansion

rem /* Replace `^^^` by `^` in order to resolve double-escaping; at this point,
rem    quoted `;` are represented by the sequence `^^;`, unquoted ones by `^;`: */
set "BUFFER=!BUFFER:^^^=^!"

rem // Escape `"`, so everything appears unquoted then:
set "BUFFER=!BUFFER:"=^^"!"

rem /* Expand immediately, so escaping is again processed;
rem    at this point, originally quoted `;` are represented by `^;`: */
set "BUFFER=!BUFFER:^=^^^!"
set ^"BUFFER=%BUFFER:!=^^!%^" !

rem // Remove all `"` from string:
set "BUFFER=!BUFFER:"=!^"

rem // Enclose whole string in `""` and replace each `;` by `";"`:
set ^"BUFFER="!BUFFER:;=";"!"^"

rem // Replace `^";"` (which are originally quoted `;`) by `;`:
set "BUFFER=!BUFFER:^";"=;!"

rem // Finally revert initial replacement of `^` by `^@`:
set "BUFFER=!BUFFER:^@=^!"

set BUFFER & echo/

rem // Eventually return the list items:
for %%I in (!BUFFER!) do (if "!!"=="" endlocal) & echo(%%~I

endlocal
exit /B

Solution 11 - Windows

This script will parse the current windows path into at txt file using JREPL.bat. It was inspired by the above post by 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%'S 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

Solution 12 - Windows

Returning to this, in the case you have node.js and inspired by Bob Stein answer for python one-liner.

node -e "console.log(process.env.path.replace(/;/g,'\n'))"

Or longer way:

node -e "console.log(process.env.path.split(';').join('\n'))"

I needed to find lines where git is installed so:

node -e "console.log(process.env.path.split(';').filter(str=>str.match(/git/i)).join('\n'))"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsamView Question on Stackoverflow
Solution 1 - WindowsjebView Answer on Stackoverflow
Solution 2 - WindowsStephen QuanView Answer on Stackoverflow
Solution 3 - Windowsuser1998693View Answer on Stackoverflow
Solution 4 - WindowsdbenhamView Answer on Stackoverflow
Solution 5 - WindowsSherylHohmanView Answer on Stackoverflow
Solution 6 - WindowsBob SteinView Answer on Stackoverflow
Solution 7 - WindowsweirView Answer on Stackoverflow
Solution 8 - WindowsMarble68View Answer on Stackoverflow
Solution 9 - WindowsaschipflView Answer on Stackoverflow
Solution 10 - WindowsaschipflView Answer on Stackoverflow
Solution 11 - Windowsslyfox1186View Answer on Stackoverflow
Solution 12 - WindowsMiro BartanusView Answer on Stackoverflow