Skip to content

Instantly share code, notes, and snippets.

@neocotic
Last active January 19, 2021 20:20
Show Gist options
  • Save neocotic/1095029 to your computer and use it in GitHub Desktop.
Save neocotic/1095029 to your computer and use it in GitHub Desktop.
INI File Utilities
:: INI File Utilities
::
:: Copyright 2011, [neocotic](http://github.com/neocotic)
:: Released under the MIT License
:: http://en.wikipedia.org/wiki/MIT_License
@echo off
setLocal enableDelayedExpansion
:: Declares required constants
set TEMP_FILE="%TEMP%\ini-%RANDOM%.tmp"
:: To be returned when script ends
:: If an unexpected problem occurs, this will be changed to reflect the level of that problem
set returnCode=0
if exist %TEMP_FILE% del /Q %TEMP_FILE%
set optClear=N
set optKeys=N
set optRemove=N
set optStrictMode=N
set optUsage=N
set optValues=N
:: Reads options one-by-one
:readOptions
set opt=%~1
if "%opt:~0,1%"=="/" (
:: Checks if usage descriptor should be printed
if "%opt:~1,1%"=="?" (
set optUsage=Y
goto nextOption
)
:: Checks if key value should be cleared
if /i "%opt:~1,1%"=="C" (
set optClear=Y
set optRemove=N
goto nextOption
)
:: Checks if only keys should be printed
if /i "%opt:~1,1%"=="K" (
set optKeys=Y
set optValues=N
goto nextOption
)
:: Checks if key should be removed
if /i "%opt:~1,1%"=="R" (
set optClear=N
set optRemove=Y
goto nextOption
)
:: Checks if an error should be thrown when accessing non-existant sections/keys
if /i "%opt:~1,1%"=="S" (
set optStrictMode=Y
goto nextOption
)
:: Checks if only values should be printed
if /i "%opt:~1,1%"=="V" (
set optKeys=N
set optValues=Y
goto nextOption
)
goto invalidOptionError
:nextOption
shift
goto readOptions
)
:: Determines if usage should be printed and whether or not to continue with process afterwards
if "%optUsage%"=="Y" goto printUsage
:process
:: Assigns parameter values to declared variables
set fileName=%~1
set section=%~2
set key=%~3
set value=%~4
:: Validates file name specified
if "%fileName%"=="" goto fileNotSpecifiedError
if not exist "%fileName%" goto fileNotFoundError
:: Determines what to print based on parameters provided
if "%section%"=="" goto printAll
if "%key%"=="" (
if "%optClear%"=="Y" goto handleSection
if "%optRemove%"=="Y" goto handleSection
goto printAllSection
)
if "%value%"=="" (
if "%optClear%"=="Y" goto handleKey
if "%optRemove%"=="Y" goto handleKey
goto printKeyValue
)
goto handleKey
:: Prints all sections contained within specified file, including their key=value pairs
:: Section headings only printed if neither /K /V options were specified
:: Keys only printed if /V option wasn't specified
:: Values only printed if /K option wasn't specified
:printAll
for /f "tokens=1,* delims==" %%A in (%fileName%) do (
set line=%%A
if "!line:~0,1!"=="[" (
set currentSection=!line!
if "%optKeys%"=="N" if "%optValues%"=="N" (
echo.
echo.!currentSection!
)
) else (
if not "!currentSection!"=="" (
if "%optKeys%"=="Y" (
echo.%%A
) else (
if "%optValues%"=="Y" (
echo.%%B
) else (
echo.%%A=%%B
)
)
)
)
)
goto end
:: Prints key=value pairs of the speciifed section contained within specified file
:: Keys only printed if /V option wasn't specified
:: Values only printed if /K option wasn't specified
:printAllSection
set sectionFound=N
for /f "tokens=1,* delims==" %%A in (%fileName%) do (
set line=%%A
if "!line:~0,1!"=="[" (
set currentSection=!line!
if /i "!currentSection!"=="[%section%]" set sectionFound=Y
) else (
if /i "!currentSection!"=="[%section%]" (
if "%optKeys%"=="Y" (
echo.%%A
) else (
if "%optValues%"=="Y" (
echo.%%B
) else (
echo.%%A=%%B
)
)
)
)
)
if "%sectionFound%"=="N" if "%optStrictMode%"=="Y" goto sectionNotFoundError
goto end
:: Prints value of the key paired under the specified section contained within specified file
:printKeyValue
set sectionFound=N
for /f "tokens=1,* delims==" %%A in (%fileName%) do (
set line=%%A
if "!line:~0,1!"=="[" (
set currentSection=!line!
if /i "!currentSection!"=="[%section%]" set sectionFound=Y
) else (
if /i "!currentSection!"=="[%section%]" (
if /i "%%A"=="%key%" (
echo.%%B
goto end
)
)
)
)
if "%optStrictMode%"=="Y" (
if "%sectionFound%"=="N" goto sectionNotFoundError
goto keyNotFoundError
) else (
echo.
)
goto end
:: Handles the key within the specified section contained within specified file
:handleKey
set keyAdded=N
set keyFound=N
set sectionFound=N
for /f "tokens=1,* delims==" %%A in (%fileName%) do (
set line=%%A
if "!line:~0,1!"=="[" (
if not "!currentSection!"=="" (
(echo.)>>%TEMP_FILE%
if /i "!currentSection!"=="[%section%]" if "!keyFound!"=="N" if "%optRemove%"=="N" (
set keyAdded=Y
if "%optClear%"=="Y" (
(echo.%key%=)>>%TEMP_FILE%
) else (
if not "%value%"=="" (echo.%key%=%value%)>>%TEMP_FILE%
)
)
)
set currentSection=!line!
if /i "!currentSection!"=="[%section%]" set sectionFound=Y
(echo.!currentSection!)>>%TEMP_FILE%
) else (
if not "!currentSection!"=="" (
if /i "!currentSection!"=="[%section%]" (
if /i "%%A"=="%key%" (
set keyFound=Y
if "%optRemove%"=="N" (
if "%optClear%"=="Y" (
(echo.%key%=)>>%TEMP_FILE%
) else (
if not "%value%"=="" (echo.%key%=%value%)>>%TEMP_FILE%
)
)
) else (
(echo.%%A=%%B)>>%TEMP_FILE%
)
) else (
(echo.%%A=%%B)>>%TEMP_FILE%
)
) else (
(echo.!line!)>>%TEMP_FILE%
)
)
)
if "%sectionFound%"=="N" if "%optRemove%"=="N" (echo [%section%])>>%TEMP_FILE%
if "%keyFound%"=="N" if "%keyAdded%"=="N" if "%optRemove%"=="N" (
if "%optClear%"=="Y" (
(echo.%key%=)>>%TEMP_FILE%
) else (
if not "%value%"=="" (echo.%key%=%value%)>>%TEMP_FILE%
)
)
goto write
:: Handles the section contained within specified file
:handleSection
set sectionFound=N
for /f "tokens=1,* delims==" %%A in (%fileName%) do (
set line=%%A
if "!line:~0,1!"=="[" (
if not "!currentSection!"=="" (echo.)>>%TEMP_FILE%
set currentSection=!line!
if /i "!currentSection!"=="[%section%]" (
set sectionFound=Y
if "%optRemove%"=="N" (echo.!currentSection!)>>%TEMP_FILE%
) else (
(echo.!currentSection!)>>%TEMP_FILE%
)
) else (
if not "!currentSection!"=="" (
if /i not "!currentSection!"=="[%section%]" (echo.%%A=%%B)>>%TEMP_FILE%
) else (
(echo.!line!)>>%TEMP_FILE%
)
)
)
if "%sectionFound%"=="N" if "%optStrictMode%"=="Y" goto sectionNotFoundError
goto write
:: Writes each line of the temporary file to the specified file
:write
set firstLine=Y
for /f "tokens=*" %%A in (%TEMP_FILE%) do (
if "!firstLine!"=="Y" (
set firstLine=N
(echo.%%A)>%fileName%
) else (
(echo.%%A)>>%fileName%
)
)
goto end
:: Provides user feedback on any unexpected errors
:fileNotFoundError
(echo [ ERROR ] File not found: %fileName%)1>&2
goto error
:fileNotSpecifiedError
(echo [WARNING] File not specified)1>&2
goto warning
:invalidOptionError
(echo [ ERROR ] Invalid option: %opt%)1>&2
goto error
:keyNotFoundError
(echo [ ERROR ] Key not found: %key%)1>&2
goto error
:sectionNotFoundError
(echo [ ERROR ] Section not found: %section%)1>&2
goto error
:: Handles exiting script correctly due to an unexcepted problem
:error
set returnCode=2
goto end
:warning
set returnCode=1
goto end
:: Prints usage descriptor for this command
:printUsage
echo Usage: ini [options] [file [section [key [value]]]]
echo Options:
echo /C clears specified key's value or section's keys
echo /K print keys only
echo /R removes specified key or section
echo /S enables strict mode
echo /V print values only
if not "%~1"=="" (
echo.
goto process
)
:end
if exist %TEMP_FILE% del /Q %TEMP_FILE%
endLocal&exit /b %returnCode%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment