Windows batch script pour lire an.fichier ini
j'essaie de lire un fichier .ini
avec le format suivant:
[SectionName]
total=4
[AnotherSectionName]
total=7
[OtherSectionName]
total=12
fondamentalement, je veux imprimer certaines valeurs du fichier .ini
, par exemple le total sous OtherSectionName
suivi du total de AnotherSectionName
.
7 réponses
voici un fichier de commande ( ini.cmd
) que vous pouvez utiliser pour extraire les valeurs pertinentes:
@setlocal enableextensions enabledelayedexpansion
@echo off
set file=%~1
set area=[%~2]
set key=%~3
set currarea=
for /f "usebackq delims=" %%a in ("!file!") do (
set ln=%%a
if "x!ln:~0,1!"=="x[" (
set currarea=!ln!
) else (
for /f "tokens=1,2 delims==" %%b in ("!ln!") do (
set currkey=%%b
set currval=%%c
if "x!area!"=="x!currarea!" if "x!key!"=="x!currkey!" (
echo !currval!
)
)
)
)
endlocal
et voici une transcription la montrant en action (j'ai indenté manuellement la sortie pour la rendre plus facile à lire):
c:\src>type ini.ini
[SectionName]
total=4
[AnotherSectionName]
total=7
[OtherSectionName]
total=12
c:\src>ini.cmd ini.ini SectionName total
4
c:\src>ini.cmd ini.ini AnotherSectionName total
7
c:\src>ini.cmd ini.ini OtherSectionName total
12
pour l'utiliser réellement dans un autre fichier cmd
, il suffit de remplacer la ligne echo %val%
ci-dessous avec ce que vous voulez en faire):
for /f "delims=" %%a in ('call ini.cmd ini.ini AnotherSectionName total') do (
set val=%%a
)
echo %val%
je sais que je suis un peu en retard à la fête, mais j'ai décidé d'écrire un script de lot d'utilitaire de fichier ini à usage général pour répondre à cette question.
le script vous permettra de récupérer ou modifier des valeurs dans un fichier de style ini. Ses recherches sont insensibles à la casse, et il conserve les lignes vierges dans le fichier ini. Essentiellement, il vous permet d'interagir avec un fichier ini comme une sorte de base de données très rudimentaire.
ce script fonctionnera très bien si vous êtes lecture / écriture seulement valeurs ou Symboles alphanumériques qui n'ont pas de signification particulière pour l'interpréteur cmd
. Si vous avez besoin de quelque chose capable de manipuler des valeurs contenant des Ampli, des percents, etc, voir la section mise à jour ci-dessous.
:: --------------------
:: ini.bat
:: ini.bat /? for usage
:: --------------------
@echo off
setlocal enabledelayedexpansion
goto begin
:usage
echo Usage: %~nx0 /i item [/v value] [/s section] inifile
echo;
echo Take the following ini file for example:
echo;
echo [Config]
echo password=1234
echo usertries=0
echo allowterminate=0
echo;
echo To read the "password" value:
echo %~nx0 /s Config /i password inifile
echo;
echo To change the "usertries" value to 5:
echo %~nx0 /s Config /i usertries /v 5 inifile
echo;
echo In the above examples, "/s Config" is optional, but will allow the selection of
echo a specific item where the ini file contains similar items in multiple sections.
goto :EOF
:begin
if "%~1"=="" goto usage
for %%I in (item value section found) do set %%I=
for %%I in (%*) do (
if defined next (
if !next!==/i set item=%%I
if !next!==/v set value=%%I
if !next!==/s set section=%%I
set next=
) else (
for %%x in (/i /v /s) do if "%%~I"=="%%x" set "next=%%~I"
if not defined next (
set "arg=%%~I"
if "!arg:~0,1!"=="/" (
1>&2 echo Error: Unrecognized option "%%~I"
1>&2 echo;
1>&2 call :usage
exit /b 1
) else set "inifile=%%~I"
)
)
)
for %%I in (item inifile) do if not defined %%I goto usage
if not exist "%inifile%" (
1>&2 echo Error: %inifile% not found.
exit /b 1
)
if not defined section (
if not defined value (
for /f "usebackq tokens=2 delims==" %%I in (`findstr /i "^%item%\=" "%inifile%"`) do (
echo(%%I
)
) else (
for /f "usebackq delims=" %%I in (`findstr /n "^" "%inifile%"`) do (
set "line=%%I" && set "line=!line:*:=!"
echo(!line! | findstr /i "^%item%\=" >NUL && (
1>>"%inifile%.1" echo(%item%=%value%
echo(%value%
) || 1>>"%inifile%.1" echo(!line!
)
)
) else (
for /f "usebackq delims=" %%I in (`findstr /n "^" "%inifile%"`) do (
set "line=%%I" && set "line=!line:*:=!"
if defined found (
if defined value (
echo(!line! | findstr /i "^%item%\=" >NUL && (
1>>"%inifile%.1" echo(%item%=%value%
echo(%value%
set found=
) || 1>>"%inifile%.1" echo(!line!
) else echo(!line! | findstr /i "^%item%\=" >NUL && (
for /f "tokens=2 delims==" %%x in ("!line!") do (
echo(%%x
exit /b 0
)
)
) else (
if defined value (1>>"%inifile%.1" echo(!line!)
echo(!line! | find /i "[%section%]" >NUL && set found=1
)
)
)
if exist "%inifile%.1" move /y "%inifile%.1" "%inifile%">NUL
exemple
contenu de example.ini
:
[SectionName]
; This is a comment.
total=4
[AnotherSectionName]
# This is another comment.
total=7
[OtherSectionName]
And it should work with non-standard comments as well.
total=12
session D'essai:
C:\Users\me\Desktop>ini /s AnotherSectionName /i total example.ini
7
C:\Users\me\Desktop>ini /s othersectionname /i Total /v f00 example.ini
f00
C:\Users\me\Desktop>type example.ini
[SectionName]
; This is a comment.
total=4
[AnotherSectionName]
# This is another comment.
total=7
[OtherSectionName]
And it should work with non-standard comments as well.
Total=f00
mise à Jour
apparemment, la pur discontinu solution étouffe quand elle rencontre des caractères comme &
(et probablement %
et d'autres). Voici donc un script hybride batch + JScript plus robuste qui résout ce problème. La syntaxe et la sortie sont les mêmes (mais avec un commutateur /d
ajouté pour supprimer les paires item=value
).
ce script définit %ERRORLEVEL%=0
pour succès, et %ERRORLEVEL%=1
sur erreur.
@if (@a==@b) @end /* -- batch / JScript hybrid line to begin JScript comment
:: --------------------
:: ini.bat
:: ini.bat /? for usage
:: --------------------
@echo off
setlocal enabledelayedexpansion
goto begin
:: color code by jeb -- https://stackoverflow.com/a/5344911/1683264
:c
set "param=^%~2" !
set "param=!param:"=\"!"
findstr /p /A:%1 "." "!param!\..\X" nul
<nul set /p ".=%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%"
exit /b
:: but it doesn't handle slashes. :(
:s
<NUL set /p "=/"&exit /b
:usage
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do set "DEL=%%a"
<nul > X set /p ".=."
echo Usage:
call :c 07 " query:"
call :c 0F " %~nx0 "&call :s&call :c 0F "i item ["&call :s&call :c 0F "s section] inifile"&echo;
call :c 07 " create or modify:"
call :c 0F " %~nx0 "&call :s&call :c 0F "i item "&call :s&call :c 0F "v value ["&call :s&call :c 0F "s section] inifile"&echo;
call :c 07 " delete:"
call :c 0F " %~nx0 "&call :s&call :c 0F "d item ["&call :s&call :c 0F "s section] inifile"&echo;
echo;
echo Take the following ini file for example:
echo;
echo [Config]
echo password=1234
echo usertries=0
echo allowterminate=0
echo;
echo To read the "password" value:
call :c 0F " %~nx0 "&call :s&call :c 0F "s Config "&call :s&call :c 0F "i password inifile"&echo;
echo;
echo To modify the "usertries" value to 5:
call :c 0F " %~nx0 "&call :s&call :c 0F "s Config "&call :s&call :c 0F "i usertries "&call :s&call :c 0F "v 5 inifile"&echo;
echo;
echo To add a "timestamp" key with a value of the current date and time:
call :c 0F " %~nx0 "&call :s&call :c 0F "s Config "&call :s&call :c 0F "i timestamp "&call :s&call :c 0F "v ""%DEL%%%%%date%%%% %%%%time%%%%""%DEL% inifile"&echo;
echo;
echo To delete the "allowterminate" key:
call :c 0F " %~nx0 "&call :s&call :c 0F "s Config "&call :s&call :c 0F "d allowterminate inifile"&echo;
echo;
call :c 07 "In the above examples, "&call :s
call :c 0F "s Config "
echo is optional, but will allow the selection of
echo a specific item where the ini file contains similar items in multiple sections.
del X
goto :EOF
:begin
if "%~1"=="" goto usage
for %%I in (item value section found) do set %%I=
for %%I in (%*) do (
if defined next (
if !next!==/i set "item=%%~I"
if !next!==/v (
set modify=true
set "value=%%~I"
)
if !next!==/d (
set "item=%%~I"
set modify=true
set delete=true
)
if !next!==/s set "section=%%~I"
set next=
) else (
for %%x in (/i /v /s /d) do if "%%~I"=="%%x" set "next=%%~I"
if not defined next (
set "arg=%%~I"
if "!arg:~0,1!"=="/" (
1>&2 echo Error: Unrecognized option "%%~I"
1>&2 echo;
1>&2 call :usage
exit /b 1
) else set "inifile=%%~I"
)
)
)
for %%I in (item inifile) do if not defined %%I goto usage
if not exist "%inifile%" (
1>&2 echo Error: %inifile% not found.
exit /b 1
)
cscript /nologo /e:jscript "%~f0" "%inifile%" "!section!" "!item!" "!value!" "%modify%" "%delete%"
exit /b %ERRORLEVEL%
:: Begin JScript portion */
var inifile = WSH.Arguments(0),
section = WSH.Arguments(1),
item = WSH.Arguments(2),
value = WSH.Arguments(3),
modify = WSH.Arguments(4),
del = WSH.Arguments(5),
fso = new ActiveXObject("Scripting.FileSystemObject"),
stream = fso.OpenTextFile(inifile, 1),
// (stream.ReadAll() will not preserve blank lines.)
data = [];
while (!stream.atEndOfStream) { data.push(stream.ReadLine()); }
stream.Close();
// trims whitespace from edges
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/,'') }
// trim + toLowerCase
String.prototype.unify = function() { return this.trim().toLowerCase(); };
// unquotes each side of "var"="value"
String.prototype.splitEx = function(x) {
for (var i=0, ret = this.split(x) || []; i<ret.length; i++) {
ret[i] = ret[i].replace(/^['"](.*)['"]$/, function(m,){return });
};
return ret;
}
// splices a new element into an array just after the last non-empty element. If first arg is a number, start at that position and look backwards.
Array.prototype.cram = function() {
for (var args=[], i=0; i<arguments.length; i++) { args.push(arguments[i]); }
var i = (typeof args[0] == "number" && Math.floor(args[0]) == args[0]) ? args.shift() : this.length;
while (i>0 && !this[--i].length) {};
for (var j=0; j<args.length; j++) this.splice(++i, 0, args[j]);
}
function saveAndQuit() {
while (data && !data[data.length - 1].length) data.pop();
var stream = fso.OpenTextFile(inifile, 2, true);
stream.Write(data.join('\r\n') + '\r\n');
stream.Close();
WSH.Quit(0);
}
function fatal(err) {
WSH.StdErr.WriteLine(err);
WSH.Quit(1);
}
if (section && !/^\[.+\]$/.test(section)) section = '[' + section + ']';
if (modify) {
if (section) {
for (var i=0; i<data.length; i++) {
if (data[i].unify() == section.unify()) {
for (var j=i + 1; j<data.length; j++) {
if (/^\s*\[.+\]\s*$/.test(data[j])) break;
var keyval = data[j].splitEx('=');
if (keyval.length < 2) continue;
var key = keyval.shift(), val = keyval.join('=');
if (key.unify() == item.unify()) {
if (del) data.splice(j, 1);
else {
data[j] = item + '=' + value;
WSH.Echo(value.trim());
}
saveAndQuit();
}
}
if (del) fatal(item + ' not found in ' + section + ' in ' + inifile);
data.cram(j ,item + '=' + value);
WSH.Echo(value.trim());
saveAndQuit();
}
}
if (del) fatal(section + ' not found in ' + inifile);
data.cram('\r\n' + section, item + '=' + value);
WSH.Echo(value.trim());
saveAndQuit();
}
else { // if (!section)
for (var i=0; i<data.length; i++) {
var keyval = data[i].splitEx('=');
if (keyval.length < 2) continue;
var key = keyval.shift(), val = keyval.join('=');
if (key.unify() == item.unify()) {
if (del) data.splice(i, 1);
else {
data[i] = item + '=' + value;
WSH.Echo(value.trim());
}
saveAndQuit();
}
}
if (del) fatal(item + ' not found in ' + inifile);
data.cram(item + '=' + value);
WSH.Echo(value.trim());
saveAndQuit();
}
}
else if (section) { // and if (!modify)
for (var i=0; i<data.length; i++) {
if (data[i].unify() == section.unify()) {
for (var j=i + 1; j<data.length; j++) {
if (/^\s*\[.+\]\s*$/.test(data[j])) fatal(item + ' not found in ' + section + ' in ' + inifile);
var keyval = data[j].splitEx('=');
if (keyval.length < 2) continue;
var key = keyval.shift(), val = keyval.join('=');
if (key.unify() == item.unify()) {
WSH.Echo(val.trim());
WSH.Quit(0);
}
}
}
}
fatal(section + ' not found in ' + inifile);
}
else { // if (item) and nothing else
for (var i=0; i<data.length; i++) {
var keyval = data[i].splitEx('=');
if (keyval.length < 2) continue;
var key = keyval.shift(), val = keyval.join('=');
if (key.unify() == item.unify()) {
WSH.Echo(val.trim());
WSH.Quit(0);
}
}
fatal(item + ' not found in ' + inifile);
}
j'ai une courte proposition pour Read config.fichier ini dans le répertoire courant de Windows batch (.chauve-souris):
près de fin de fichier de lot nous coller ce code:
:ini
@for /f "tokens=2 delims==" %%a in ('find "%~1=" config.ini') do @set %~2=%%a
@goto:eof
et près du début du fichier de lot nous l'appelons par:
@call:ini IniFieldName batchVarName
@echo IniFieldName is: %batchVarName%
config.ini
foo=string
bar=123
baz=spaces work too!
windows_batch.cmd
for /F "tokens=*" %%I in (config.ini) do set %%I
vieille question mais j'en avais besoin récemment et j'ai trouvé la réponse à @paxdiablo. J'avais besoin de quelque chose de plus, alors j'ai enrichi sa réponse et je donne maintenant en retour.
ce dont j'avais aussi besoin, c'était de trouver quelle clé avait une valeur spécifique. Aussi, soutenez explicitement la section racine (aucun nom de section).
Voici mon code, une fonction que j'ai mise dans une bibliothèque (variable CMDLib) que j'appelle quand j'en ai besoin (entre autres fonctions).
:ReadINI
REM ReadINI - Get value from [Section]; Key from an INI File.
REM Arguments:
REM File INI-file to read from
REM Key Name of the entry
REM Section Name of the [Section] under which the Value is.
REM Optional, will find a value from the root section if empty.
REM For root section, set to "-" to also use "Value"
REM Value If Key is set to "-", will find which Key has "Value"
REM
REM Returns: A string of text will be echoed, ready for logging.
REM An echo of the value.
REM
REM Call example:
REM for /f "delims=" %%a in ('Call "%CMDLib%" ReadINI "Inifile" Key Section') do ( set Value=%%a)
REM
REM Original: http://stackoverflow.com/a/2866328/151152
rem ------- Function header -------
Setlocal ENABLEDELAYEDEXPANSION
:: Logging formatting
if not defined nest (set /a nest=0) else set /a Nest=%nest%+1
if %nest% GEQ 1 if not defined _tab (set _tab= ) else for /l %%i in (0, %nest%,1) do set _tab=%_tab%
rem ------- Function body -------
set file=%~1
set key=%~2
set Section=[%~3]
if "%Section%"=="-" set Section=
set value=%~4
set currSection=
Set RC=0
for /f "usebackq delims=" %%a in ("%file%") do (
set ln=%%a
if "x!ln:~0,1!"=="x[" (
set currSection=!ln!
) else (
for /f "tokens=1,2 delims==" %%b in ("!ln!") do (
set currkey=%%b
set currval=%%c
if /i "x!Section!"=="x!currSection!" (
if /i "x!key!"=="x!currkey!" (
echo !currval!
if %_D% GEQ 2 echo %_tab%[%0 - RC:%RC%]
exit /b %RC%
) Else if "x!key!"=="x-" (
if /i "x!value!"=="x!currval!" (
echo !currkey!
if %_D% GEQ 2 echo %_tab%[%0 - RC:%RC%]
exit /b %RC%
)
)
)
)
)
)
if %_D% GEQ 2 echo %_tab%[%0 - RC:%RC%]
Exit /b %RC%
rem ------- Function end -------
Pas de mise en évidence de la syntaxe pour CMD? C'est une honte.. ;- )
Espérons que cela aide les autres.
hmm, peut-être que ça aide quelqu'un.. A dû le construire depuis inifile.exe est à court d'astuces et semble que chaque fichu analyseur ini sur le web a besoin de " clé " alors que tout ce dont j'ai besoin est toutes les valeurs sous [section]. Voici l'empreinte de la section..
@echo off
SETLOCAL DisableDelayedExpansion
IF "%1"=="" (echo Usage: section input.ext output.ext & goto eof )
IF "%2"=="" (echo Usage: section input.ext output.ext & goto eof )
IF NOT EXIST "%2" (echo File does not exist. Usage: section input.ext output.ext & goto eof )
IF "%3"=="" (echo Usage: section input.ext output.ext & goto eof )
FOR /F "tokens=*" %%A IN ('findstr /I /N "\[.*\]" %2') DO (echo %%A>>LINE_START.DAT)
FOR /F "tokens=1,2 delims=:" %%A IN ('findstr /I "\[%1\]" LINE_START.DAT') DO (
SETLOCAL EnableDelayedExpansion
set FIRSTLINE=%%A
)
set /a "FIRSTLINE+=1"
FOR /F "tokens=1,2* delims=:" %%A IN ('findstr /I /N ".*" %2') DO (
IF %%A GEQ !FIRSTLINE! (echo %%B>>LINE_END.DAT)
)
set ENDLINE=500
FOR /F "tokens=1,2* delims=:" %%A IN ('findstr /I /N "\[.*\]" LINE_END.DAT') DO (
IF %%A LSS !ENDLINE! (set /a "ENDLINE=%%A") ELSE echo %%A>nul
)
set /a "ENDLINE-=1"
FOR /F "tokens=1,2* delims=:" %%A IN ('findstr /I /N ".*" LINE_END.DAT') DO (
IF %%A LEQ !ENDLINE! (echo %%B>>%3) ELSE ENDLOCAL
)
set ENDLINE=0
set FIRSTLINE=0
ENDLOCAL
DEL /Q LINE_*.DAT
:end
Ouais, ouais je sais qu'il semble que c'est de l'arrière, mais il fonctionne, bien que, pas sûr qu'il fonctionnera avec des espaces dans le dossier ou des espaces dans les fichiers. Construit fondamentalement juste .fichier ini dans le même dossier et exécuté depuis la ligne de commande.
Usage: genetix_ini.entrée de la section cmd.sortie en ext.poste 151920920"
mise à jour n ° 2: On dirait que j'ai fait une erreur en ne mettant pas à zéro les 2 ensembles de var. Ce qui a commencé à causer un problème au second passage du script.