extracting a changing and unknown hashcode from text document in batch - batch-file

i wanted to code a little update tool for a server.jar file to save me all the effort of doing it manually
the program i'm using creates a folder which contains a file when a new update is released. this is pretty much how the program works:
get hash of current server.jar
find latest created folder (eg. update12)
open the file in the update12 folder (eg. update12.txt)
***extract the hash code -> %newHash%*** thats where im having the issue
compare the extracted hashcode (%newHash%) and the calculated hashcode (%currentHash%)
if they are not equal go to www.downloadupdate.com/updates/%newHash%/server.jar
download the file and replace the old server.jar with the new one.
the issue i am having is that i cant read out the hash in the update12.txt the file is about 36000 symbols long and in one line only
"server": {"sha1": "16f18c21286a3f566d3d0431d13aa133bebe6eff"
i want to detect the "server": {"sha1": " part and copy the hash after that
i tried many options i found on this forum but none seemed to work
like this one
set /p txt=<update12.txt
pause >nul
echo %txt%
pause >nul
for /f %%i in ('powershell -noprofile -c "('%txt:"=\"%' -split '\""')[1]"') do set id=%%i
echo %id%
just caused the batch file to close instantly
furthermore set /p txt=
if you have any solution i would be grateful to hear it

#echo off
Setlocal EnableDelayedExpansion
xcopy %appdata%\.minecraft\versions\%MCversion%\%MCversion%.json %appdata%\.minecraft\versions\%MCversion%\%MCversion%.text*
ren %appdata%\.minecraft\versions\%MCversion%\%MCversion%.text %MCversion%.txt
set search1=
set search2=,
set search3=:
set textFile=%appdata%\.minecraft\versions\%MCversion%\%MCversion%.txt
:PowerShell
SET PSScript=%temp%\~tmpStrRplc.ps1
ECHO (Get-Content "%textFile%").replace("%search1%", "") ^| Set-Content "%textFile%">"%PSScript%"
Powershell -ExecutionPolicy Bypass -Command "& '%PSScript%'"
SET PSScript=%temp%\~tmpStrRplc.ps1
echo done.
ECHO (Get-Content "%textFile%").replace("%search2%", "") ^| Set-Content "%textFile%">"%PSScript%"
Powershell -ExecutionPolicy Bypass -Command "& '%PSScript%'"
SET PSScript=%temp%\~tmpStrRplc.ps1
echo done.
ECHO (Get-Content "%textFile%").replace("%search3%", "") ^| Set-Content "%textFile%">"%PSScript%"
Powershell -ExecutionPolicy Bypass -Command "& '%PSScript%'"
SET PSScript=%temp%\~tmpStrRplc.ps1
echo done.
:skip
ECHO (Get-Content "%textFile%").replace("server", "`r`nlookup") ^| Set-Content "%textFile%">"%PSScript%"
Powershell -ExecutionPolicy Bypass -Command "& '%PSScript%'"
echo done.
for /f %%a in ('findstr "lookup\"{\"sha1\"\"" %textFile%') do set "newVersion=%%a"
set newVersion=%newVersion:~15,40%
echo %newVersion%
del %textFile%
pause
:exit
exit
this code works for me, what it does:
copy the "update12.txt"
look for " " "," and ":" in the copied txt and delete the symbols
look for server replace it with a "*linebreak*lookup"
find the string lookup"{"sha1""
trim the edges of the string with 15,40
done.

Related

CMD: Sort files in folder structure

I am trying to create a BAT that automatically sorts the ZIPs in the input folder into the corresponding target folder.
All ZIPs begin with a serial number 001 File.zip, 002 File.zip, 003 File.zip, etc.
The target folders are named according to the same scheme: 001, 002, 003, ..., 999.
So if a ZIP comes into the input folder, it should automatically be assigned to the corresponding target folder with the same number.
But since the target folder is up to 999 I don't want to write all paths beforehand ...
So far my code looks like this:
SET input=C:\Daten\Input
SET target=C:\Daten\Target
for /r %input% %%a in (*.zip) do (
Set FILE=%%~nxa
Set FILEWITHOUTEXT=%%~na
Set SPLITABLE_NAME=!FILEWITHOUTEXT:_= !
for %%t in (!SPLITABLE_NAME!) do set FIRSTTOKEN=%%t
)
copy /Y %%a %target%\!FIRSTTOKEN!\!FILE!
Unfortunately, the whole thing just doesn't work at all.
Based on Stephan's comment and some additional code cleanup and best practice usage your code should look like this.
:sort
SET "input=C:\Daten\Input"
SET "target=C:\Daten\Target"
for /r "%input%" %%a in (*.zip) do (
For /f "tokens=1 delims=_ " %%t in ("%%~na") do (
copy /Y "%%~a" "%target%\%%t\"
)
)
I see that you have already selected and answer. If you wanted to push ahead into a modern day scripting language, you could consider using PowerShell. If you are on a supported Windows platform, PowerShell will be available.
Once you are confident that the files will be correctly copied, remove the -WhatIf from the Copy-Item command.
powershell -NoLogo -NoProfile -Command ^
"Get-ChildItem -File -Path 'C:\Daten\Input' -Filter '???_*.zip' |" ^
'ForEach-Object {" ^
"if ($_.Name -match '^(\d{3})_.*') {" ^
"Copy-Item $_.FullName "C:\Daten\Target\$($Matches[1])" -Whatif" ^
"}" ^
"}"

Conditional concatenation in batch

I am trying to append an underscore to strings when they are not blank. This is for a backup program, where the name of the folder is [prefix]_[date]_[time]_[suffix], except the first and last underscores are supposed to only be added when the [prefix] or [suffix] are not empty.
I've attempted to concatenate with set PRX=%PRX% and _ as I read on some forum, although the and wasn't recognized (it just outputted "backup and _"). I also tried jumping around the files with "goto", but to no avail. I think it's with the concatenation.
#echo off
set /p DRV=Enter drive/directory to back up (e.g. %userprofile% or C:):
set /p DRU=Enter directory to save to (e.g. C:\backup or F:):
set /p PRX=Enter the prefix for the directory. Directory will be saved as [prefix]_[date]_[time]_[suffix]:
set /p SFX=Enter the suffix for the directory. Directory will be saved as [prefix]_[date]_[time]_[suffix]:
if %PRX% NEQ "" (set PRX=%PRX%_)
if %SFX% NEQ "" (set SFX=_%SFX%)
set /p CONT=%CD%, Are you sure you want to continue (Y/N)?
if /i "%CONT%" EQU "N" goto :cancel
cls
echo Initialising...
%DRV:~0,1%:
cd\
set DAT=%date:~6,4%-%date:~3,2%-%date:~0,2%
set TIM=%time:~0,2%-%time:~3,2%-%time:~6,2%
mkdir "%DRU%\%PRX%%DAT%_%TIM%%SFX%"
echo Cloning Files...
echo.
xcopy "%DRV%\*" "%DRU%\%PRX%%DAT%_%TIM%%SFX%" /s
I inputted
Enter drive/directory to back up (e.g. %userprofile% or C:): %userprofile%\downloads
Enter directory to save to (e.g. C:\backup or F:): %userprofile%\backup
Enter the prefix for the directory. Directory will be saved as [prefix]_[date]_[time]_[suffix]: (that is empty)
Enter the suffix for the directory. Directory will be saved as [prefix]_[date]_[time]_[suffix]: aa
the outputted folder was named "_2019-09-10_17-08-35_aa" as opposed to "2019-09-10_17-08-35_aa", not what I was expecting.
I appreciate any reply, thank you for your time.
String comparison is very explicit.
IF "%PRX%" NEQ "" (SET "PRX=%PRX%_")
IF "%SFX%" NEQ "" (SET "SFX=_%SFX%")
It is easy to get correctly formatted data and time values regardless of region settings.
FOR /F %%A IN ('powershell -NoLogo -NoProfile -Command "Get-Date -Format 'yyyy-MM-dd'"') DO (
SET "DAT=%%A"
)
FOR /F %%A IN ('powershell -NoLogo -NoProfile -Command "Get-Date -Format 'HH-mm-ss'"') DO (
SET "TIM=%%A"
)

How to read different contents from a text file

I need to read the ID from a file like this:
BitLocker Drive Encryption: Configuration Tool version 10.0.16299
Copyright (C) 2013 Microsoft Corporation. All rights reserved.
Volume C: [OSDisk]
All Key Protectors
External Key:
ID: {31116007-D1FB-43CC-A89C-927487BD5F00}
External Key File Name:
31116007-D1FB-43CC-A89C-927487BD5F00.BEK
Numerical Password:
ID: {C7948F32-F2F0-4E55-AD2E-06E982DFDB4F}
Password:
xxxx-xxxxx-xxxxx-xxxxxx-xxxxx-xxxx-xxxxx-xxx
TPM:
ID: {6497FF93-F678-4317-B5D7-423E9D682BF0}
PCR Validation Profile:
0, 2, 4, 8, 9, 10, 11
and then run the following command to to export the keys to AD for all IDs
manage-bde -protectors -adbackup c: -id {C7948F32-F2F0-4E55-AD2E-06E982DFDB4F}
If you're not willing to utilise another built-in scripting language for this, and your file to read uses Windows standard line endings, I have an alternative idea.
Instead of directly searching for lines with ID: {…, you may be able to search for <Anything><Carriage Return><Line Feed><Space(s)><Password:>. You could further refine <Anything> should you feel the need, but in this case I do not think it's necessary:
#Echo Off
SetLocal DisableDelayedExpansion
Set "Src=input.txt"
Set "Str=Password:"
Set "ID="
(Set LF=^
% 0x0A %
)
For /F %%A In ('Copy /Z "%~f0" Nul')Do Set "CR=%%A"
SetLocal EnableDelayedExpansion
FindStr /RC:".*!CR!*!LF! *%Str%" "%Src%">"%TEMP%\_$.tmp"
EndLocal
For /F "UseBackTokens=2Delims={}" %%A In ("%TEMP%\_$.tmp")Do Set "ID={%%A}"
Del "%TEMP%\_$.tmp"
If Not Defined ID GoTo :EOF
manage-bde -protectors -adbackup c: -id %ID%
In the example above, I have used input.txt as the name of the text file you're reading, please modify that as needed.
FOR /f "tokens=2delims={}" %%a IN ('findstr /x /r /c:" *ID: {.*}" "%filename1%"') DO ECHO manage-bde -protectors -adbackup c: -id {%%a}
where filename1 contains the filename you are examining and the command is being echoed. Remove the echo keyword to execute manage-bde.
The findstr looks for lines that exactly match the pattern [spaces]ID: {string} and assigns the string between {} to %%a, then displays the required command line, reapplying the {}
a pure batch script, which takes advantage of the fact, you look for the key immediately after a "trigger line" (Numerical Password:)
#echo off
setlocal
set "flag="
for /f "tokens=*" %%a in (t.txt) do (
if defined flag (for %%b in (%%a) do set "key=%%b") & goto :found
if "%%a" == "Numerical Password:" set "flag=yes"
)
echo not found & goto :eof
:found
echo %key%
Perhaps use a windows script to handle the task? This can be executed directly, using wscript, or from a batch file using cscript:
cscript //nologo myscript.js
var fso = new ActiveXObject("Scripting.FileSystemObject");
var file = fso.OpenTextFile("C:\\myfile.txt", 1);
var content = file.readAll();
// Do something with file content
file.close();
You might be able to get what want with Regular Expressions and FindStr. Partial solution since I'm lazier than you. ;)
c:\projects>findstr {[0-9A-F/-]*} data.txt
ID: {31116007-D1FB-43CC-A89C-927487BD5F00}
ID: {C7948F32-F2F0-4E55-AD2E-06E982DFDB4F}
ID: {6497FF93-F678-4317-B5D7-423E9D682BF0}
EDIT: I overlooked that all IDs and created a solution based on the example line
The following PowerShell one liner will extract the ID from a text file .\BitLocker.txt
PoSh> Select-String -Path .\BitLocker.txt -Pattern 'Numerical Password' -Context 0,1|ForEach-Object {($_.Context.Postcontext.Trim() -split ' ')[1]}
{C7948F32-F2F0-4E55-AD2E-06E982DFDB4F}
To be on topic wrapped in a batch:
#Echo off
For /f "usebackq delims=" %%A in (`
powershell -NoP -C "Select-String -Path .\BitLocker.txt -Pattern 'Numerical Password' -Context 0,1|% {($_.Context.Postcontext.Trim() -split ' ')[1]}"
`) Do Set "ID=%%A"
manage-bde -protectors -adbackup c: -id %ID%

Display Line (n) in a text file In Command Prompt

My text file include with 23 lines (lines include: !#$:/;" )
How can i only display line 3? in or 7? or 19?
I tried all commands was in stackoverflow
Example:
setlocal enabledelayedexpansion
#echo off
for /f "delims=" %%i in (mytext.txt) do (
if 1==1 (
set first_line=%%i
echo !first_line!
goto :eof
))
that's only show first line
#Compo has given a good answer. This is only to expound on it. Using aliases like GC should not be put into scripts. At the command line, sure, go ahead and reduce typing if you feel like it. Also, spelling out the parameter names provides more information and aids faster understanding.
To get only line 3.
GC .\mytext.txt -T 3|Select -L 1
Get-Content -Path '.\mytext.txt' -TotalCount 3 | Select-Object -Last 1
From the CMD console (Command prompt): (to get only line seven (7)
PowerShell "GC .\mytext.txt -T 7|Select -L 1"
PowerShell -NoProfile "Get-Content -Path '.\mytext.txt' -TotalCount 7 | Select-Object -Last 1"
To get lines 3 through 7:
$FirstLine = 3
$LastLine=7
powershell -NoProfile -Command "Get-Content -Path '.\t.txt' -TotalCount $LastLine | Select-Object -Last ($LastLine - $FirstLine + 1)"
Or, in a cmd.exe batch script.
SET "FIRSTLINE=3"
SET "LASTLINE=7"
powershell -NoProfile -Command ^
"Get-Content -Path '.\t.txt' -TotalCount %LASTLINE% |" ^
"Select-Object -Last (%LASTLINE% - %FIRSTLINE% + 1)"
#echo off
setlocal
set "FILE_TO_PROCESS=%~f1"
set /a LINE_NUMBER=%~2
set /a trim=LINE_NUMBER-1
break>"%temp%\empty"&&fc "%temp%\empty" "%FILE_TO_PROCESS%" /lb %LINE_NUMBER% /t |more +4 | findstr /B /E /V "*****"|more +%trim%
endlocal
try with this bat (called lineNumber.bat) the first argument is the file you want to process the second is the line number:
call lineNumber.bat someFile.txt 5
There are a couple of ways to do this. Your first option is to go through the for loop normally and break out of the loop once you reach the desired line.
#echo off
:: Specify which line to return
set get_line=7
:: Skip all lines before it, then print the next line and abort
set /a get_line-=1
for /F "skip=%get_line% delims=" %%A in (mytext.txt) do (
echo %%A
goto :end_loop
)
:end_loop
Your other option is to store all lines before the unwanted line in a temp variable and then display the next line.
#echo off
setlocal enabledelayedexpansion
:: Specify which line to return
set get_line=7
:: Skip all lines before it, then print the next line and abort
set /a get_line-=2
(
for /L %%A in (0,1,%get_line%) do set /p skip_line=
set /p return_line=
) <file.txt
echo !return_line!
Note that the first option is not suited for returning the first line of the script.
Since you said 'display', why not give PowerShell a shot:
From the PowerShell console:
GC .\mytext.txt -T 3|Select -L 1
From the CMD console (Command prompt):
PowerShell "GC .\mytext.txt -T 7|Select -L 1"
From a batch file:
#(PowerShell "GC .\mytext.txt -T 19|Select -L 1"&Pause)

Pass variable from batch to powershell

I have a batch file that ask the user for a variable line set /p asset=. Im calling my powershell script like this
SET ThisScriptsDirectory=%~dp0
SET PowerShellScriptPath=%ThisScriptsDirectory%file.ps
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '%PowerShellScriptPath%'";
Im wondering how i send powershell the variable 'asset' from my batch file.
Here is my .bat file content
#Echo off
cls
Color E
cls
#echo Enter asset below
set /p asset=
#echo.
#echo your asset is %asset%
#echo.
goto startusmt
:startusmt
#echo.
#echo executing psexec ...
#echo.
SET ThisScriptsDirectory=%~dp0
SET PowerShellScriptPath=%ThisScriptsDirectory%RemoteUSMT.ps1
PowerShell -NoProfile -ExecutionPolicy Bypass -file %PowerShellScriptPath% %asset%
psexec \\%asset% -u domain\username -p password cmd
goto EOF
:EOF
PAUSE
You can use $env:variable_name syntax to access curent cmd environment variables from powershell. To get hold of your variable you'd use $env:asset
To try, open cmd, do set "myvar=my value", start powershell, do $env:myvar (this will simply print it, but of course you can use it as any other ps variable)
Just as a sidenote, ps has good help system. If you do help env it will list two relevant topics which you can examine in turn to get detailed information.
Hope this helps
If you have a file.ps1 that takes a parameter,
param($asset)
"The asset tag is $asset"
You can pass in the variable as an argument.
SET ThisScriptsDirectory=%~dp0
SET PowerShellScriptPath=%ThisScriptsDirectory%file.ps1
SET /p asset=Enter the asset name
PowerShell -NoProfile -ExecutionPolicy Bypass -file "%PowerShellScriptPath%" "%asset%"
param($asset)
This has to be the very first line in the PowerShell script for it to work, else it will fail.

Resources