How to use FINDSTR to strip lines with % from robocopy logfile? - special-characters

I would like to strip all the lines with a % progress-value from my robocopy logfiles. The lines look like this:
*EXTRA Datei 7.3 g test.pst
Neuer 7.3 g huge.PST
0.0%
0.0%
0.0%
0.1%
0.1%
0.1%
0.1%
99.8%
99.9%
99.9%
99.9%
99.9%
99.9%
100%
Neue Datei 7.5 g another.PST
0.0%
I'm not successful with this attempt
FINDSTR.exe /V "%" LogFile.txt > LogFileWithoutPercentageLines.txt
because this cuts too much lines away (in the above example the entire line with huge.PST and another.PST)
The %-lines includes two spaces before 0.0% and a CR.
The %-lines includes one space before 10.0% and a CR.
The %-line includes no space before 100.0% but two spaces after 100% and a CR.
How can I get rid of this useless 0.0% until 100% lines only with FINDSTR?

Use robocopy with /NP switch, cf Logging Options in robocopy /?:
/NP :: No Progress - don't display percentage copied.
For instance, robocopy "%_source%" "%_target%" /log:"%temp%\38610436.log" /NP
However, next commented script shows a possible way of removing all that unwanted progress stuff from an existing weed-infested log file (findstr itself does not suffice for this complex task):
#ECHO OFF >NUL
SETLOCAL EnableExtensions DisableDelayedExpansion
set "_source=d:\bat\odds and ends\B" rem change to match your circumstances
set "_target=d:\bat\odds and ends\Bcopy" rem detto
set "_logFileRawData=%temp%\38610436.log" rem detto
set "_logFileCleaned=%temp%\38610436a.log" rem detto
rem /NP : No Progress - don’t display % copied
rem robocopy "%_source%" "%_target%" /log:"%temp%\38610436.log" /NP
robocopy "%_source%" "%_target%" /log:"%temp%\38610436.log"
>"%_logFileCleaned%" (
for /f "usebackq tokens=1,* delims=:" %%G in ( `findstr /N "^" "%_logFileRaw%"` ) do (
set "_line=%%H"
call :strip_Progress
SETLOCAL EnableDelayedExpansion
echo(!_line!
ENDLOCAL
)
)
ENDLOCAL
goto :eof
:strip_Progress
set "_zero=" rem zero percent indicator
set "_line=%_line%" rem remove all Carriage Return characters
rem after above command, _line with progress could be, excluding Square Brackets:
rem [New File 0 ZeroFile.ext100% ]
rem [New File 51808 TinyFile.txt 0% 100% ]
rem [Newer 1.1 m Mid_File.ext 0% 21% 42% 64% 85% 100% ]
rem [New File 162.1 m Big_File.ext 0.0% 0.6% 1.2% … 99.3% 99.9%100% ]
if "%_line%"=="" goto :eof
if "%_line:~-6%"=="100%% " call :removeProgress
goto :eof
:removeProgress
set "_line=%_line:~0,-6%" rem strip six trailing characters
if defined _zero goto :eof
rem as yet, zero percent indicator not set
:stripTrailingSpace
if "%_line:~-2%"==" " set "_line=%_line:~0,-1%" & goto :stripTrailingSpace
if "%_line:~-4%"==" 0%%" set "_zero=4" & set "_line=%_line%x%%"
if "%_line:~-6%"==" 0.0%%" set "_zero=6"
if "%_line:~-1%"=="%%" goto :removeProgress
goto :eof
Further resources (required reading, incomplete):
(command reference) An A-Z Index of the Windows CMD command line
(helpful particularities) Windows CMD Shell Command Line Syntax
(%G, %H etc. special page) Command Line arguments (Parameters)
(special page) EnableDelayedExpansion
(>, & etc. special page) Redirection
(%_line:~0,-6% etc.) Extract part of a variable (substring)
(%% doubled percent sign) Escape Characters, Delimiters and Quotes

Related

Script to compare file size of one file

I am trying to write a script that tell me if a file file size is greater than a number, below is the script I have written, but it keeps showing 1999 even though I know the file size is greater than the number.
#echo off
setlocal enabledelayedexpansion
for /f "delims=" %%a in (' powershell -c "(Get-ChildItem -Recurse "C:\XSTOREDB\xstore_data.mdf" | Measure-Object -Property Length -Sum).Sum" ') do set "foldsize=%%a"
if "!foldsize!" GTR "6000000000" (
exit /B 0
) else (
exit /B 1999
)
endlocal
I'm pretty sure you have 2 problems. The first problem is that you are doing an alphabetical comparison. Thus, "7" would be considered GTR "6000000000".
Your second problem is that numeric operations in cmd are limited to 32 bit integers. The maximum number you can use is 2^31 - 1, which is 2147483647, which is already less than the number you are interested in.
The typical workaround here is to either compare the "important" parts of the string, or truncate the N least significant digits.
Here is a quick example. It may contain issues/errors in implementation. I did echo exit /b so the script would run and you can see the results instead of actual exit /b.
#echo off
setlocal enabledelayedexpansion
rem first we will inspect the 10th and 11th digits from the right
set foldsize=7000000010
rem If there is any number in the 11th spot, then it must be greater
if not "!foldsize:~0,-10!"=="" (
rem the number is at least 10000000000 which is greater so we exit
echo exit /B 0
)
rem check if the 10th digit is 6 or greater
rem add a zero to avoid issues with an undefined variable
set smallfoldsize=!foldsize:~0,-9!
if !smallfoldsize!0 GTR 50 (
rem technically the number is now greater or equal to 6000000000
rem I will leave it up to you if you really need it to be greater than
echo exit /B 0
) else (
rem it is smaller
echo exit /B 1999
)
rem an alternative is to discard the N least significant digits
rem I am stripping the last 7 digits and then adding a zero to avoid
rem an undefined variable
set smallfoldsize=!foldsize:~0,-7!0
if !smallfoldsize! GEQ 6000 (
echo exit /B 0
) else (
echo exit /B 1999
)
rem again, this is actual greater or equal. If you
rem need greater than, you have to look at the less
rem significant digits when smallfoldsize = 6000
avery_larry's helpful answer does a great job of explaining the fundamental problems with your approach (lexical rather than numerical comparison, numbers that are too large).
If your comparison doesn't need to be accurate down to the byte level, you can try the following approach, which enables a simpler solution:
Make PowerShell return a value in mebibytes (MiB) rather than bytes.
This should return a small enough number that you can compare (numerically) with cmd's GTR operator.
#echo off
setlocal enabledelayedexpansion
for /f "delims=" %%a in ('
powershell -noprofile -c ^
"[math]::Ceiling((Get-ChildItem -File -Recurse \"C:\XSTOREDB\xstore_data.mdf\" | Measure-Object -Property Length -Sum).Sum / 1mb)"
') do set "foldsize=%%a"
:: # 6000000000 bytes is ca. 5722 MB
if !foldsize! GTR 5722 (
exit /B 0
) else (
exit /B 1999
)
Note how the PowerShell command divides the result by 1mb (1 MiB (mebibyte) = 2 ^ 20 = 1,048,576 bytes) and then rounds it up via [math]::Ceiling()
Also note how the embedded " chars. were escaped as \" to ensure that PowerShell sees them.
Finally, note how, as a small optimization, -File was passed to the Get-ChildItem cmdlet in order to skip directories (themselves, not their files), given that directories themselves have no Length property.
Despite your question body, text, and title, not matching the code you have supplied, I do not see any need for a for-loop for this task.
Based upon your question body text, and title, to exit with an errorlevel of 0 if file C:\XSTOREDB\xstore_data.mdf is greater than 6GB:
#"%__AppDir__%WindowsPowerShell\v1.0\powershell.exe" -NoP "If(Test-Path -L "C:\XSTOREDB\xstore_data.mdf"){(GI -L "C:\XSTOREDB\xstore_data.mdf").Length -GT 6GB}" 2>NUL|"%__AppDir__%find.exe" "T">NUL&&(Exit /B 0)||Exit /B 1999
Based upon your question code, to exit with an errorlevel of 0 if directory C:\XSTOREDB totals more than 6GB:
#"%__AppDir__%WindowsPowerShell\v1.0\powershell.exe" -NoP "If(Test-Path -L "C:\XSTOREDB"){(GCI "C:\XSTOREDB" -Rec|Measure Length -Su -EA Stop).Sum -GT 6GB}" 2>NUL|"%__AppDir__%find.exe" "T">NUL&&(Exit /B 0)||Exit /B 1999

batch file to open txt replace text save and close

I understand that this community is for helping people and I'm not one hundred percent how to ask for someone to do a commissioned job or w/e but I'd like a series of batch files for changing certain numbers to a particular number per batch file.
echo off
if exist %application.yml del %application.yml
for /F "delims=" %%l in (%1) do (
set "line=%%l"
set "line=%line:specific text=another word%"
echo/%line%>> %application.yml)'
How would I set this to replace an array of numbers to the set number, I'm sorry I'm a complete idiot with this.
File itself application.yml
product:
# Cntrl alt 1 Mini, 2 m16, 3 scar, 4 m4169, 5 akm, 6 ump,7 sks
discordUsername:
discordPassword:
maxCPUsUsage: 4
shutdownKey: 0x7B
reloadConfigKey: 0x79
screenResolutionX: 1920
screenResolutionY: 1080
playerEsp: true
playerEspColor: 0xFF00FF
playerEspPointSize: 1
radarEsp: true
radarEspColor: 0x0000FF
radarEspPointSize: 2
vehicleEsp: true
vehicleEspColor: 0xff0000
vehicleEspPointSize: 1
vehicleEspHotkey: 0x2D
lootEsp: true
lootEspColor: 0x00FF00
lootAirdropEspColor: 0xffffff
lootEspPointSize: 1
lootEspHotkey: 0x24
redrawTime: 0
reloadDataTime: 2000
aimEnabled: true
aimKey: 0x39
aimFOV: 95
aimFrequency: 6
aimPrecision: 1
aimSpeed: 1
bulletSpeed: 990
aimHitbox: 0
# Key list: https://msdn.microsoft.com/en-us/en-en/library/windows/desktop/dd375731(v=vs.85).aspx
So essentially the number I wish to replace is the bullet speed and it could be multiple numbers from previous changes ect, for example
990
870
400
and if it is any of these instances I wish to replace it with
900
and so on and so forth.
So it searches for any of the possible numbers and changes it to the specified number and save the file under the same file name.
Thanks in advance for any help if I'm being completely honest in the example I dont even know what to change to make it simply replace one number to the other never mind multiple instance searches :)
Once again ty for any advice or help.
The following commented .bat script should do the job, although empty lines are not copied to output file:
#ECHO OFF
SETLOCAL EnableExtensions
rem redirect all output to a brand new file
>application.yml (
rem parse a file (supplied file name %1 must not be equal to "application.yml")
for /F "usebackq delims=" %%l in ("%~1") do (
rem parse each line
for /F "tokens=1* delims=:" %%L in ("%%~l") do (
if /I "%%~L"=="bulletSpeed" (
rem modified line
echo(%%L: 900
) else (
rem original line
echo(%%l
)
)
)
)
BTW, in the original script, you would need Delayed Expansion to make proper reference to variables (re)defined within a parenthesised code block (like a FOR loop body), e.g. as follows:
echo off
SETLOCAL EnableExtensions EnableDelayedExpansion
if exist application.yml del application.yml
for /F "delims=" %%l in (%1) do (
set "line=%%l"
set "line=!line:specific text=another word!"
echo/!line!>>application.yml
)
Resources (required reading):
(command reference) An A-Z Index of the Windows CMD command line
(helpful particularities) Windows CMD Shell Command Line Syntax
(%~L etc. special page) Command Line arguments (Parameters)
(special page) EnableDelayedExpansion
(>>, > etc. special page) Redirection
Regular Expressions are ideal to do this sort of editing.
Aside from findstr's limited capabilities batch is lacking RE support.
This wrapped powershell one liner will do the job either on cmd line or in a batch-file.
powershell -NoP -C "(gc application.yml) -Replace '(?<=bulletSpeed: )\d+','900'|sc application.yml"
It uses a lookbehind assertion to replace any number following bulletSpeed: with 900.
To limit the replacement to one of previous 990, 870, 400 use this:
powershell -NoP -C "(gc application.yml) -Replace '(?<=bulletSpeed: )(990|870|400)','900'|sc application.yml"

Loop through each line of text file and run command against each

I am trying to adjust some code which is shown below and hitting walls.
The commandline appears as:
cmd.exe /U /C "C:\Program Files\StorageCraft\ShadowProtect\VerifyImages.cmd <PathOfDirectoryWhichContainsImageFiles> <PathToOutputLogFile>
The code basically runs an image verify command against all md5 files in a directory. The problem is that some directories have >200 md5 files and I only want to verify the files created in the last 24 hrs.
I have been able to create a list of the files created in the last 24hrs and output to a text file using a powershell command.
Is it possible to adjust the script below so that it reads the text file line by line and runs the VERIFY_SUB against each? I have tried using the FOR /F command with little luck to this point.
Thanks in advance.
REM *** START OF MAIN ROUTINE ***
SETLOCAL
PUSHD
CD /D %~dp0
REM Strip the outer quotes off of the directory parameter
SET PARAM_DIR=%1
SET PARAM_DIR=###%PARAM_DIR%###
SET PARAM_DIR=%PARAM_DIR:"###=%
SET PARAM_DIR=%PARAM_DIR:###"=%
SET PARAM_DIR=%PARAM_DIR:###=%
REM Strip the outer quotes off of the output log file parameter
SET PARAM_OUTPUT_FILE=%2
SET PARAM_OUTPUT_FILE=###%PARAM_OUTPUT_FILE%###
SET PARAM_OUTPUT_FILE=%PARAM_OUTPUT_FILE:"###=%
SET PARAM_OUTPUT_FILE=%PARAM_OUTPUT_FILE:###"=%
SET PARAM_OUTPUT_FILE=%PARAM_OUTPUT_FILE:###=%
FOR %%A IN ("%PARAM_DIR%\*.md5") DO (call :VERIFY_SUB "%%A" "%PARAM_OUTPUT_FILE%")
POPD
ENDLOCAL
GOTO :EOF
REM *** END OF MAIN ROUTINE ***
:VERIFY_SUB
#ECHO VERIFYING MD5 FILE %1
#ECHO VERIFYING MD5 FILE %1 >> %2
image.exe v %1 >> %2
#ECHO. >> %2
#ECHO. >> %2
#ECHO. >> %2
GOTO :EOF

rename multiple files in order with command prompt

I have some files with different names.
Leviathan.txt,Dragon.txt and so on
I wanted to turn it into a digit begins
1.txt,2.txt,3.txt,4.txt and so on
how to perform like other language by using For and function that can pass amount files in folder?
my code so far i know is dir and ren. and i stuck now.
ren *.txt 1.txt
Next code snippet could work for you (save with .bat extension); note that rename command is echoed merely for debugging purposes:
#echo off
SETLOCAL enableextensions enabledelayedexpansion
set /A "ii=0"
pushd "working_directory_here"
for /F "delims=" %%G in ('dir /B /ON "*.txt" 2^>NUL') do (
set /A "ii+=1"
echo ren "%%~G" "!ii!%%~nxG"
)
popd
If you insist on an one-liner (launch in proper working directory):
cmd /E:ON /V:ON /K (#echo off^&set /A "ii=0" ^>NUL^&for /F "delims=" %G in ('dir /B /ON "*.txt" 2^^^>NUL') do (set /A "ii+=1" ^>nul^&echo ren "%~G" "!ii!%~nxG"))^&exit
Resources (required reading):
(command reference) An A-Z Index of the Windows CMD command line
(additional particularities) Windows CMD Shell Command Line Syntax
(%~G etc. special page) Command Line arguments (Parameters)
(EnableDelayedExpansion) Setlocal EnableDelayedExpansion
(^>, %% etc.) Syntax : Escape Characters, Delimiters and Quotes
Assuming none of your existing files are already named something like n.txt, where n is a number, then simply CD to your folder, and run the following command from the command line:
for "tokens=1* delims=:" %A in ('dir /b *.txt^|findstr /n "^"') do #ren "%B" "%A.txt"
Double up the percents if you use the command within a batch script.
EDIT
I forgot about my JREN.BAT utility - a regular expression renaming utility. It is pure script (hybrid JScript/batch) that runs natively on any Windows machine from XP onward.
JREN has a built in ability to incorporate a number into each new file name, and as an added bonus, it can left pad the number with zeros so that a DIR command lists the files in numerical order. The default numeric width is 3 digits, so files would be like "001.txt", "002.txt', ... "010.txt", ... "100.txt", etc.
jren "^.*" "$n+'.txt'" /j /fm *.txt
The /NPAD option specifies the minimum numeric width, so NTAB 1 produces no padding, which is what the original question asked for.
jren "^.*" "$n+'.txt'" /j /fm *.txt /npad 1
Since JREN is a batch script itself, you must use CALL JREN if you put the command within another batch script.
Full documentation is available from the command prompt via jren /? | more. My console window is configured with a large buffer, so I can scroll back to see prior output, and I don't bother with piping the help to MORE.

eol unix to windows in command line .bat batch

I am trying to convert text file eol to windows format from unix on windows xp machine using command line (batch file). how do I do that? what is the command for that? thanks.
This simple script is fast and works great except it converts every TAB character into 8 spaces. The number of spaces can be modified with the MORE /T option, but there is no way to preserve the TAB characters. Pass the file name (optionally with path) as the one and only argument.
#echo off
more %1 >%1.new
move /y %1.new %1 >nul
All that is needed is to read and echo each line. The FOR /F command is perfect, except it ignores empty lines. Here I use FINDSTR to prefix each line with the line number, followed by a :, thus preserving empty lines. Then I use search and replace to remove the number prefix. I must toggle delayed expansion on and off within the loop to preserve any ! that may appear. This script preserves TABs, but is limited to ~8191 bytes per line. It is also relatively slow. It will become very slow with very large files.
#echo off
setlocal disableDelayedExpansion
>%1.new (
for /f "delims=" %%A in ('findstr /n "^" %1') do (
set "ln=%%A"
setlocal enableDelayedExpansion
echo(!ln:*:=!
endlocal
)
)
move /y %1.new %1 >nul
Finally, here is a hybrid batch/JScript solution that is very fast, and does not have any limitations that I am aware of.
#if (#X)==(#Y) #end /* Harmless hybrid line that begins a JScript comment
::************ Batch portion ***********
#echo off
<%1 cscript //E:JScript //nologo "%~f0" >%1.new
move /y %1.new %1 >nul
exit /b
************* JScript portion **********/
while (!WScript.StdIn.AtEndOfStream) {
WScript.Stdout.WriteLine(WScript.StdIn.ReadLine());
}