why when I run it first thing in the morning I get hundreds of results
#echo off
:: it only shows files on you pc that arrived that day.
SETLOCAL EnableDelayedExpansion
DIR /b /s /a c:\*.* >todays.txt
set count=0
FOR /F "usebackq tokens=* delims=," %%G IN ("todays.txt") DO (call :sub1 "%%G")
echo Todays file count=%count%
pause
:: end of program
:sub1
set dat=%~t1
SET fdate=%dat:~0,8%
if "%fdate%"=="%date%" (
echo.%count% %1 %dat%
set /a count=%count%+1
)
goto :eof
why when I run it first thing in the morning I get hundreds of results
Since you're only interested in files, I'd change the /a switch (which does nothing) to /a-d to suppress directorynames which would be reported as a "file".
There's really no point in specifying tokens=* with a delims since the tokens=* will reproduce the line regardless.
Related
I'm trying to write a very simple batch file for personal use...It's complete except for one thing I'm stumped on. Hopefully this is an easy fix (I'm effectively illiterate when it comes to code).
Basically what I'm trying to do is have the script choose a random line from a text file, do this a couple times with a couple different text files, then I wish to assign the output from each text file to a variable so that I can easily use them in various combinations...then repeat the process.
Here is what I have right now...
#ECHO OFF
:START
SETLOCAL
SETLOCAL EnableDelayedExpansion EnableExtensions
SET "list1=list1.txt"
FOR /f %%a IN ('type "%list1%"^|find /c /v ""') DO SET /a numlines=%%a
SET /A list1random=(%RANDOM% %% %NumLines%)
IF "%list1random%"=="0" (SET "list1random=") ELSE (SET "list1random=skip=%list1random%")
FOR /F "usebackq tokens=* %list1random% delims=" %%A IN (`TYPE %list1%`) DO (
>> output.txt ECHO %%A
)
:Finish
ENDLOCAL
GOTO START`
This procures the random line, and spits it to a text file. All is well, next step, take that random result and assign it to a variable...
#ECHO OFF
:START
SETLOCAL
SETLOCAL EnableDelayedExpansion EnableExtensions
SET "list1=list1.txt"
FOR /f %%a IN ('type "%list1%"^|find /c /v ""') DO SET /a numlines=%%a
SET /A list1random=(%RANDOM% %% %NumLines%)
IF "%list1random%"=="0" (SET "list1random=") ELSE (SET "list1random=skip=%list1random%")
FOR /F "usebackq tokens=* %list1random% delims=" %%A IN (`TYPE %list1%`) DO (
SET output1=%%A
)
>> output.txt ECHO %output1%
:Finish
ENDLOCAL
GOTO START
Now the output ceases to be random...instead it is always the last line of the referenced text file.
EDIT: The site suggested another question that was similar to mine. However, that person was having trouble getting the script to choose a valid line. I get a valid line every time, and a random one too (when I check it via echo), but a non-random line when proceeding on, assigning the output to a variable. I don't understand because it seems like a post-facto derandomization. I.E. the difference between the two scripts has nothing to do with procuring the random result, only what to do with that result AFTER it has it, right?
I appreciate any help in advance, this is the last step before I know everything I need to finish this, I'm excited!
Sorry, you're right...anyways, I figured out a simple workaround, probably not the quickest in terms of processing time, but whatever. Basically allow the initial part of the script to spit out the random result to a text file (as seemed to work just fine) then reference the text file as a variable.
#ECHO OFF
:START
SET "list1=list1.txt"
FOR /f %%a IN ('type "%list1%"^|find /c /v ""') DO SET /a numlines=%%a
SET /A listchoice=(%RANDOM% %% %NumLines%)
IF "%listchoice%"=="0" (SET "listchoice=") ELSE (SET "listchoice=skip=%listchoice%")
FOR /F "usebackq tokens=* %listchoice% delims=" %%A IN (`TYPE %list1%`) DO (
>> listoutput.txt ECHO %%A
)
Set /p list=<listoutput.txt
>> result.txt ECHO %list%
:Finish
DEL listoutput.txt
GOTO START
This is easy to do in PowerShell using the built-in Get-Random cmdlet.
$line = (Get-Content file.txt | where { $_ } | Get-Random)
Which makes it also easy in batch.
set filename=file.txt
for /f "tokens=*" %%a in ('powershell -ex bypass -c "gc %filename% | ? { $_ } | Get-Random"') do (
set "var=%%a"
)
The where { $_ } clause is only necessary to filter out any blank lines. You can omit it if you know your file has none.
This is my first posting so if the format is not as it supposed to be please excuse me for this. (Suggestions for
improvement are welcome.)
I am trying to create a batchfile that will read last lines from logfiles and copy them to a new file.
Until now I have found here a way to read the last line.
Code would be something like:
for /f %%i in ('find /v /c "" ^< someFile.txt') do set /a lines=%%i
set /a startLine=%lines% - 1
more /e +%startLine% someFile.txt > lastLines.txt
The above code works for one file at a time. What I need is to read the last line from all files in a known list and add this line to a new .csv file.
I have been using the following code for getting the 4th entry in the logfiles but it returns every line of every logfile:
for /f %%x in (%list%) do for /f "delims=.txt, tokens=4" %%i in (%%x.txt) do echo %%x, %%i >> output.csv
What I would need is a sort of combination of both but I don't know how to combine them and make the complete last line be copied to the .csv file.
===
#Magoo:
Thanx for your reaction.
In every logfile can be 1 to >100 lines with comma separated information. Something like:
"LOGON,6-1-2015,12:43:39,USERNAME,HOSTNAME,,,,192.168.209.242,00:21:5A:2E:64:5E"
The last code with the 4th entry was used to get a list of all accounts that had logged in to the computers. This code gave me a very large list of all logon/logoff events on all computerlogs I checked in %list%.
In %list$ I had all the names of logfiles I wanted to be checked. This returned all lines.
For a new batchfile I need only the last logon/logoff entry and I want the whole last line.
So I have a .txt file with the hostnames of all computers I need to examine.
This .txt file will be read line by line via the variable %list%.
From every logfile I need only the last line copied to an output file.
===
I just tried the solution offered by JosefZ. Unfortunately this does not work for me yet. No lastlines are copied to the resultfile. In the code I removed the extra entry for possible lastlines for there are no empty lines in the logs, I also added an entry for the hostname I want to be available in the result. JosefZ had the filename there:
#ECHO OFF >NUL
#SETLOCAL enableextensions disabledelayedexpansion
type nul>output.csv
set "list=_listing.txt"
for /F "tokens=*" %%x in ('type "%list%"') do (
set "host=%%~x"
for /F "tokens=*" %%G in ('type "%%~x"') do set "lastline=%%G"
call :lline
)
:endlocal
#ENDLOCAL
goto :eof
:lline
set "filename=.\logs\%filename:&=^&%.txt"
echo %host%,%lastline%>>output.csv
goto :eof
The resultfile shows only the hostnames. I'll puzzle some more with this but all tips are welcome!
===
Got it!!!
#ECHO OFF >NUL
#SETLOCAL enableextensions disabledelayedexpansion
type nul>output.csv
set "list=_listing.txt"
for /F "tokens=*" %%x in ('type "%list%"') do (
set filename= :: *empty previous filename*
set lastline= :: *empty previous lastline*
set "host=%%~x"
set "filename=.\logs\%host%.txt" :: *creating the filename from path+hostname+extention*
for /F "tokens=*" %%G in ('type "%filename%"') do set "lastline=%%G"
call :lline
)
:endlocal
#ENDLOCAL
goto :eof
:lline
echo %host%,%lastline%>>output.csv
goto :eof
Your approach with line numbering could fail if a file has more trailing empty lines. Fortunately for /F loop ignores (does not iterate) empty lines; let's put to use this feature: in the script used next practices:
disabledelayedexpansion to allow ! in file names
set "list=_listing.txt" where the _listing.txt contains list of file names (full path and extension .txt including), one file name on one line: got by dir /b /s *.txt>_listing.txt
type nul>files\output.csv to empty the output file (optional)
set "lastline=!!!file empty!!!" to initialize variable %lastline%; could be set "lastline=" as well
call :lline to process variables %filename% and %lastline%
set "filename=%filename:&=^&%" to allow & in file names
The script is as follows:
#ECHO OFF >NUL
#SETLOCAL enableextensions disabledelayedexpansion
type nul>files\output.csv
set "list=_listing.txt"
for /F "tokens=*" %%x in ('type "%list%"') do (
set "filename=%%~x"
set "lastline=!!!file empty!!!"
rem the whole line
for /F "tokens=*" %%G in ('type "%%~x"') do set "lastline=%%G"
rem the fourth token only
rem for /F "tokens=4" %%G in ('type "%%~x"') do set "lastline=%%G"
call :lline
)
:endlocal
#ENDLOCAL
goto :eof
:lline
set "filename=%filename:&=^&%"
echo %filename% %lastline%
rem >>files\output.csv
goto :eof
Sample _listing.txt file:
d:\bat\files\1exclam!ation.txt
d:\bat\files\2exc!lam!ation.txt
d:\bat\files\11per%cent.txt
d:\bat\files\12per%cent%.txt
d:\bat\files\17per%Gcent.txt
d:\bat\files\18per%%Gcent.txt
d:\bat\files\21ampers&nd.txt
d:\bat\files\22ampers&&nd.txt
Output:
d:\bat>lastlines
d:\bat\files\1exclam!ation.txt 0 15.01.2015 1:52:28.48 -15072 20465
d:\bat\files\2exc!lam!ation.txt 6 15.01.2015 1:52:28.50 3250 16741
d:\bat\files\11per%cent.txt -8 15.01.2015 1:52:28.50 -3692 27910
d:\bat\files\12per%cent%.txt !!!file empty!!!
d:\bat\files\17per%Gcent.txt 0 15.01.2015 1:52:28.56 14508 12374
d:\bat\files\18per%%Gcent.txt 1 15.01.2015 1:52:28.56 30540 26959
d:\bat\files\21ampers&nd.txt 15.01.2015 1:22:50.18
d:\bat\files\22ampers&&nd.txt 15.01.2015 1:22:50.18
Honestly, all that ballast is for (possibly) trailing empty lines in files and for (possibly) ! and & in file names only; all could be done with
for /f %%x in (%list%) do for /f "skip=%startLine% tokens=4" %%i in (%%x) do echo %%x, %%i >> output.csv
You should use a simple FOR to iterate a list of values, not FOR /F.
Something like the following should work:
#echo off
setlocal enableDelayedExpansion
>>output.csv (
for %%F in (
"file1.log"
"file2.log"
"file3.log"
etc.
) do (
for /f %%A in ('find /v /c "" <%%F') do set /a skip=%%A-1
more +!skip! %%F
)
)
The quotes around the file names are there in case you get a name with spaces.
You could use your LIST variable if it looks something like
set LIST="file1.log" "file2.log" "file3.log" etc.
#echo off
setlocal enableDelayedExpansion
set LIST="file1.log" "file2.log" "file3.log" etc.
>>output.csv (
for %%F in (%LIST%) do (
for /f %%A in ('find /v /c "" <%%F') do set /a skip=%%A-1
more +!skip! %%F
)
)
If any of your file names contain the ! character, then you must toggle delayed expansion ON and OFF within your loop. Otherwise the delayed expansion will corrupt the names when %%F is expanded.
#echo off
setlocal disableDelayedExpansion
set LIST="file1.log" "file2.log" "file3.log" etc.
>>output.csv (
for %%F in (%LIST%) do (
for /f %%A in ('find /v /c "" <%%F') do set /a skip=%%A-1
setlocal enableDelayedExpansion
more +!skip! %%F
endlocal
)
)
I have a file (MyFile.txt) with a string like this, for example:
var1,var2,asds,123,var6
This file is generated automatically, and I don't know how many words it will have.
I make a for to print all words, one in each line. And process them one by one
for /f "tokens=1-30 delims=," %%a in (MyFile.txt) do call Process.bat %%a
In Process.bat I have ping %1 for example.
This only processes the first token. My problem is, I need to process all tokens, but I need to do it automatically, is there a way to loop over all existing tokens?
In my example: var1,var2,asds,123,var6 it would be: do call Process.bat %%a, then %%b, then %%c, then %%d and %%e.
Thank you.
This will work even if you have various line in Myfile.txt
#echo off&cls
for /f "delims=" %%a in (MyFile.txt) do for %%b in (%%a) do call Process.bat %%b
What about this:
set /p var=<MyFile.txt
set var="%var%"
for %%a in ("%var:,=" "%) do call Process.bat %%a
That Should work.
Mona
you can combine for to read all your lines and call to parse the vars in the line
try this to get you started
#echo off
setlocal enabledelayedexpansion
for /f %%a in (file.txt) do (
set line=%%a
set line=!line:,= !
call :parms !line!
)
goto :eof
:parms
if "%1"=="" goto :eof
echo ping %1
shift
goto :parms
goto :eof
Ok, here's the set up:
I have a ton of text files with the following format:
filename## time Description of file with spaces
I'm trying to rename the actual file on disk with the description of the file, using a for loop:
FOR /F "tokens=1,2,*" %%a IN (%1) DO call :rename %%a %%b "%%c"
goto :eof
:rename
set origfilename=%1
set last2=%1:~-2%
set time=%2
set "multiword=%~3"
ren %origfilename%.ext "%last2%_%time%_%multiword%.ext"
set origfilename=
set last2=
set time=
set multiword=
Here's what's happening:
last2 is never picking up the last 2 characters of the original file name, and if I echo %3 after the DO instead of the call to :rename, it has the full token with spaces. When I try to use %3 in the loop, it only contains the first token of %3.
I tried using setlocal EnableDelayedExpansion before the for, but it didn't work as I expected.
Am I trying to do too many things at once? Thanks for the help!
Try this. I think this will do what you want.
#echo off
for /f "Tokens=1,2,3*" %%a in ('dir /b filename*') do (
call :rename "%%a %%b %%c %%d" %%a %%b "%%c %%d")
goto :eof
:rename full orig time new
echo %2
set last2=%2
set last2=%last2:~-2%
echo ren "%~1.ext" "%last2%_%3_%~4.ext"
Remove the Echo if everything looks good
I'm making a script that copies random folders from source to destination until that folder is full (knowing that the destination folder is smaller then the source.
All the individual parts are working as intended, but I'm now running the script without the copy included (just an echo) so basically if there aren't any folders larger then the remaining space in the destination directory, it should be running for ever.
But it stops at an average of 5 iterations while there isn't any folder large enough to fill up the directory. This is the code I'm using
EDIT: got it olmost working, but now sometimes a needed_space outputs 0
#ECHO off
setlocal EnableDelayedExpansion
SET n=0
SET SOURCE_PATH=M:\Movies
SET DEST_PATH=E:\Movies
:: get all folders in dir
FOR /f "usebackq tokens=*" %%a in (`DIR /b/a:d %SOURCE_PATH%`) do (
SET /A n+=1
SET folder[!n!]=%%a
)
:loop
:: selecting ranodm number
SET /A rand=(n*%random%)/32768+1
:: check for space
for /F "tokens=3" %%S in ('dir /-c "%SOURCE_PATH%\!folder[%rand%]!\*" ^| findstr /c:"File(s)"') DO set NEEDED_SPACE=%%S
FOR /f "tokens=1*delims=:" %%i IN ('fsutil volume diskfree %DEST_PATH%') DO SET FREE_SPACE=%%j
ECHO %FREE_SPACE% - %NEEDED_SPACE%
IF %NEEDED_SPACE% GTR %FREE_SPACE% GOTO done
:: check if file does not exits
IF EXIST %DEST_PATH%\!folder[%rand%]! GOTO loop
:: copy file
ECHO moving %SOURCE_PATH%\!folder[%rand%]! to %DEST_PATH%\!folder[%rand%]!
:: again
GOTO loop
:done
ECHO Done copying random folders, have fun!
1.- You dont have taken in consideration the environment space exhausting. Maybe you can not create the array you are intending.
2.- fsutil volume diskfree ... always return the space in VOLUME, no matter if you indicate a directory
3.-if command do numeric comparisons ONLY when all the characters in both sides of the operator are numeric. Your () disables it, so (10) is less than (3)
Ok, this is working so far. waiting for the disk to get full if that works, this should be sufficient (not 100% perfect check but close enough)
code:
#ECHO off
setlocal EnableDelayedExpansion
SET n=0
SET SOURCE_PATH=M:\src
SET DEST_PATH=E:\dest
:: get all folders in dir
FOR /f "usebackq tokens=*" %%a in (`DIR /b/a:d %SOURCE_PATH%`) do (
SET /A n+=1
SET folder[!n!]=%%a
)
:loop
:: selecting ranodm number
SET /A rand=(n*%random%)/32768+1
:: check for space
for /F "tokens=3" %%a in ('dir /-c "%SOURCE_PATH%\!folder[%rand%]!" ^| findstr /c:"File(s)"') do set bytesfree=%%a
set bytesfree=%bytesfree:,=%
set /a NEEDED_SPACE=%bytesfree:~0,-3%
for /f "tokens=3" %%a in ('dir %DEST_PATH%\') do set bytesfree=%%a
set bytesfree=%bytesfree:,=%
set /a FREE_SPACE=%bytesfree:~0,-3%
ECHO %FREE_SPACE% - %NEEDED_SPACE%
IF %NEEDED_SPACE% GTR %FREE_SPACE% GOTO done
:: check if file does not exits
IF EXIST %DEST_PATH%\!folder[%rand%]! GOTO loop
:: copy file
set src="%SOURCE_PATH%\!folder[%rand%]!\*"
set dest= "%DEST_PATH%\!folder[%rand%]!\*"
ECHO moving %src% to %dest%
xcopy /s /e /i %src% %dest%
:: again
GOTO loop
:done
ECHO Done copying random folders, have fun!