I have the following batch file which outputs limited info. How do I suppress all output from this batch file? What I'd like to see is after I enter the name of the batch file and hit enter, the next thing that shows up on screen is "C:>".
#ECHO OFF
SETLOCAL EnableDelayedExpansion
(for /f "tokens=1 delims=;" %%A in (C:\ALL.txt) do (
#echo %%A | find /i "\"
if errorlevel 1 (
DEL "D:\!mypath!%%A" >> C:\ALL-OUT.txt 2>&1
) ELSE (
set mypath=%%A
)))
#endlocal
I think it all boils down to this line which I use to test whether %%A contains backslash:
#echo %%A | find /i "\"
I tried adding " 1>null" to the end of the line. It worked to suppress all output. However, it also created a file named "null".
Since "For /f" parses files line by line, I wonder if there is a way to incorporate the echo command in "For /f"?
The NUL device is referenced with nul, not null. >null creates a file named null.
for your second question: you can redirect the output of a command block with a single redirection (in fact, this is way faster)
#ECHO OFF
SETLOCAL EnableDelayedExpansion
(
for /f "delims=;" %%A in (C:\ALL.txt) do (
echo %%A | find "\" >nul
if errorlevel 1 (
DEL "D:\!mypath!%%A"
) ELSE (
set mypath=%%A
)
)
) > C:\ALL-OUT.txt 2>&1
endlocal
Related
So, basically I want a Batch file to read a .txt. The problem is that the Batch file needs to update everytime a new line gets written to the .txt
#echo off
set "pc=%1"
FOR /F "delims=:" %%A IN ('findstr /N .* "%pc%"') DO set "zeilen=%%A"
type %pc%
set /A zeilen1=%zeilen%
:loop
if not %zeilen% == %zeilen1% (
set "line="
set zeilen2=%zeilen% - 1
for /f %%a in ('more/e +%zeilen2% ^< %pc%') do (
if not defined line set "line=%%a"
)
echo %line%
set /A zeilen+=1
)
FOR /F "delims=:" %%A IN ('findstr /N .* "%pc%"') DO set "zeilen1=%%A
goto loop
I also can't use the type command (line 9-13) because I don't want to refresh the whole .txt only the last line.
sry for my poor english
Thanks
To start the Batch you need to do something like this call batch.cmd txtname.txt
A basic tail command can be written like so. Credit to #dbenham for his initial solution on DosTips.com
#echo off
call :Loop <"tailme.txt"
exit
:Loop
set "line="
set /p "line="
if defined line (
echo %line%
) else (
pathping -q 1 -p 300 localhost >nul
)
goto :loop
If you don't wish to use third party options and wish to keep it pure batch, it is very possible. From your question, it sounds like you wish to read the last line of a text file and have it update that text each time the text file is edited. Further more, this batch file much be call'ed to when it needs to be used.
To do this, we can compare the date it was last modified using forfiles in an for loop. The reason for this is that if we use the file properties EX: ECHO Last-Modified Date : %%~ta we will not get the properties down to seconds. Thus the file will only compare down to the minutes.
Now that we can grab the last modified properties we can use an IF statement to look for when the file get a new time stamp. From there we can use a modified script that reads only the last line of a text file (Configurable by set /a LINES=LINES+1 LINES+1 - Infin) made by #Patrick Cuff
To call this batch file you will want to use call ReadFile.bat txtname.txt
Call - Command
ReadFile.bat - Name of batch script
txtname.txt - Name of textfile to read
Bellow is the full script.
ReadFile.bat
#ECHO OFF
#GOTO READ
:LOOP
Rem | Look for changes
FOR /f %%a in ('forfiles /M %1 /C "cmd /c echo #fdate-#ftime"') DO (set FileTimeCurrent=%%a)
IF "%FileTimeLoad%"=="%FileTimeCurrent%" (goto LOOP) else (goto READ)
:READ
cls
Rem | Get current date
FOR /f %%a in ('forfiles /M %1 /C "cmd /c echo #fdate-#ftime"') DO (set FileTimeLoad=%%a)
Rem | Get the number of lines in the file
set LINES=0
for /f "delims==" %%I in (%1) do (
set /a LINES=LINES+1
)
Rem | Print the last line
set /a LINES=LINES-1
more +%LINES% < %1
goto LOOP
For help on any of the commands do the following:
call /?
set /?
for /?
if /?
So on.
#echo OFF
#find /c /i "james" "C:\Users\ersojt\Desktop\Sample\*.eml" > NUL
if %ERRORLEVEL% EQU 0 (
move "C:\Users\ersojt\Desktop\Sample\*.eml" "C:\Users\ersojt\Desktop\Sample2"
) else (
#echo Failure
)
PAUSE
I am trying to use a Batch file to search for a specific file containing an input; then moving this file to another directory.
Can anyone help me?
#echo OFF
setlocal enableextensions disabledelayedexpansion
set "source=C:\Users\ersojt\Desktop\Sample\*.eml"
set "target=C:\Users\ersojt\Desktop\Sample2"
set "searchString=james"
set "found="
for /f "delims=" %%a in ('
findstr /m /i /l /c:"%searchString%" "%source%" 2^>nul
') do (
if not defined found set "found=1"
echo move "%%a" "%target%"
)
if not defined found (
echo Failure
)
pause
This will use a findstr command to search for files containing the indicated search string. /m switch is used to only retrieve the matching file names.
The findstr is executed by a for /f command that will retrieve its output and, for each line in the output, execute the code in the do clause, with the line stored in the for replaceable parameter (%%a in this sample).
Move operations are only echoed to console. If the output is correct remove the echo that prefixes the move command.
I had to write a .Bat file in MS-Command prompt to extract 2 specific strings "Username" and "last login time" from a folder having say a 100 log files and each of these log file has these 2 things. The output must be printed to a csv file report to be saved somewhere.
echo Processing user's last login time. Please wait...
S:
cd log_files
for %G IN (*.txt) do (findstr /i "Username: Log-In" "%G" >> S:\Sourav\GIS_Login_Time.txt)
echo Execution Complete.
echo Output file created in C:\data folder.
pause
The output file (in txt format) is like below :
*** OS Username: ADIELA
*** GIS Username: adiela ( Laura Adie - Horizons, Bullion )
*** Log-In Time: 21/07/2014 06:37:20
*** OS Username: allanj1
*** GIS Username: allanj ( Jim Allan - Shared access Lomond House )
*** Log-In Time: 17/12/2014 11:44:22
...
Could you please advise how to modify the output (which goes to a text file now) to go into a csv file? The output file must have 3 columns. 1)OS Username 2) GIS USername 3) Log-In time.
I would greatly appreciate if I could get some valuable suggestions for this.
Thank you in advance :)
Another perfect problem for my JREPL.BAT utility - a hybrid JScript/batch script that performs a regular expression search and replace on text. JREPL.BAT is pure script that runs natively on any Windows machine from XP onward.
Assuming every file has all three entries in the same order (though not necessarily consecutively), then this one liner will create "output.csv". Note that I used line continuation just so the code is easier to read.
type *.txt 2>&1 | jrepl ^
"OS Username:\s*(.*?)$[\s\S]*?GIS Username:\s*(.*?)$[\s\S]*?Log-In Time:\s*(.*?)$" ^
"'\x22'+$1+'\x22,\x22'+$2+'\x22,\x22'+$3+'\x22'" ^
/m /jmatch /o output.csv
-- OUTPUT using your example text --
"ADIELA","adiela ( Laura Adie - Horizons, Bullion )","21/07/2014 06:37:20"
"allanj1","allanj ( Jim Allan - Shared access Lomond House )","17/12/2014 11:44:22"
If you truly want just the GPS username, without the parenthesized info, then you don't need quotes because your data no longer contains commas:
type *.txt 2>&1 | jrepl ^
"OS Username:\s*(.*?)$[\s\S]*?GIS Username:\s*(.*?)\s[\s\S]*?Log-In Time:\s*(.*?)$" ^
"$1+','+$2+','+$3" ^
/m /jmatch /o output.csv
-- OUTPUT --
ADIELA,adiela,21/07/2014 06:37:20
allanj1,allanj,17/12/2014 11:44:22
It is easy to add the header line that lists the column names:
type *.txt 2>&1 | jrepl ^
"OS Username:\s*(.*?)$[\s\S]*?GIS Username:\s*(.*?)\s[\s\S]*?Log-In Time:\s*(.*?)$" ^
"$1+','+$2+','+$3" ^
/jbeg "output.WriteLine('OS Username,GIS Username,Login Time')" ^
/m /jmatch /o output.csv
-- OUTPUT --
OS Username,GIS Username,Login Time
ADIELA,adiela,21/07/2014 06:37:20
allanj1,allanj,17/12/2014 11:44:22
This was a good one.
Here is how I solved it:
#ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
SET SourceFile="C:\SourceFile.txt"
SET OutputFile="C:\List.txt"
SET TempFile1="%TEMP%\1.txt"
SET TempFile2="%TEMP%\2.txt"
SET TempFile3="%TEMP%\3.txt"
REM Initialize files.
ECHO Header>%TempFile1%
ECHO Header>%TempFile2%
ECHO Header>%TempFile3%
IF EXIST %OutputFile% DEL %OutputFile%
REM Build a list of each value.
FOR /F "usebackq tokens=1,* delims=:" %%A IN (`FINDSTR /L "OS" %SourceFile%`) DO ECHO %%B>>%TempFile1%
FOR /F "usebackq tokens=1,* delims=:" %%A IN (`FINDSTR /L "GIS" %SourceFile%`) DO ECHO %%B>>%TempFile2%
FOR /F "usebackq tokens=1,* delims=:" %%A IN (`FINDSTR /L "Log-In" %SourceFile%`) DO ECHO %%B>>%TempFile3%
REM All temp files should have the same number of entries.
REM Concatenate them with a comma.
SET Skip=1
:ProcessLine
REM Keep going until we find the first empty entry.
REM This means we reached the end of the list.
SET "OSUserName="
SET "GISUserName="
SET "LogInTime="
REM Only set the first line.
FOR /F "usebackq tokens=* skip=%Skip% delims= " %%A IN (%TempFile1%) DO IF "!OSUserName!"=="" SET OSUserName=%%A
FOR /F "usebackq tokens=* skip=%Skip% delims= " %%A IN (%TempFile2%) DO IF "!GISUserName!"=="" SET GISUserName=%%A
FOR /F "usebackq tokens=* skip=%Skip% delims= " %%A IN (%TempFile3%) DO IF "!LogInTime!"=="" SET LogInTime=%%A
ECHO %OSUserName%
REM Check for the end of the list.
IF "%OSUserName%"=="" GOTO Finish
REM Add to the output.
ECHO %OSUserName%,%GISUserName%,%LogInTime%>>%OutputFile%
REM Increment counter and loop.
SET /A Skip=%Skip%+1
GOTO ProcessLine
:Finish
REM Cleanup.
IF EXIST %TempFile1% DEL %TempFile1%
IF EXIST %TempFile2% DEL %TempFile2%
IF EXIST %TempFile3% DEL %TempFile3%
ENDLOCAL
This builds your csv directly from the source files (without a temporary file):
#echo off
setlocal enabledelayedexpansion
REM write first line:
echo OSUser;GISUser;LoginTime >out.csv
REM for every .txt file:
for %%i in (*.txt) do (
REM add the three strings:
set "x="
for /f "tokens=1,* delims=:" %%a in ('findstr "Username Log-In" %%i') do set x=!x!%%b;
REM delete any "two consecutive spaces":
set x=!x: =!
REM delete TABs ( it's a TAB between : and = ):
set x=!x: =!
REM delete last ; (if it disturbes you):
set x=!x:~0,-1!
REM write it to the file:
echo !x!>>out.csv
)
Script:
pushd "\\server1\share\Data\"
for %%p in (*.pdf) do if /i ".pdf"=="%%~xp" for /f "tokens=1 delims=_" %%n in ("%%~np") do (
copy "%%~fp" ""\\server2share\data\%%~n\%%~nxp" dir >> \\server\share\logfile.txt
)
I want to log the output everytime this command runs. The script copies pdf's based on name. But when i run the script. No log file is created.
EDITED to adapt to comments
pushd "\\server1\share\Data\"
set "logFile=\\server\share\logfile.txt"
for %%p in (*.pdf) do if /i ".pdf"=="%%~xp" for /f "tokens=1 delims=_" %%n in ("%%~np") do (
if not exist ""\\server2share\data\%%~n\" (
>>"%logFile%" echo SKIPPED : "%%~nxp"
) else (
copy "%%~fp" "\\server2share\data\%%~n\%%~nxp"
if errorlevel 1 (
>>"%logFile%" echo FAILED : "%%~nxp"
) else (
>>"%logFile%" echo COPIED : "%%~nxp"
)
)
)
popd
You have a dir command in a strange place, changed to echo. And, i'm not sure all the paths are right.
pushd "\\server1\share\Data\"
for %%p in (*.pdf) do if /i ".pdf"=="%%~xp" for /f "tokens=1 delims=_" %%n in ("%%~np") do (
md "\\server2share\data\%%~n" 2>nul
copy "%%~fp" "\\server2share\data\%%~n\%%~nxp"
dir >> \\server\share\logfile.txt
)
(untested)
I'm assuming the way your scrip is arranged from your original post.
If you want to execute a sequence of separate commands, they need to be separated by & or be on separate lines.
You had an extra " in your copy command
Inserted a md command with error-message-suppression to ensure the destination directory exists.
This will create a log of what is shown on the cmd screen while it is running, but you will not see any output on the screen. You can use a tee filter if you also need to see the screen output.
mybatch.bat>file.log
How to delete last n lines from file using batch script
I don't have any idea about batch files, I am writing batch file for the first time.
How should I write this batch file?
For Windows7
Try it for
<Project_Name>
<Noter>
<Common>
<File>D:\Project_Name\Util.jar</File>
<File>D:\Project_Name\Noter.bat</File>
<File>D:Project_Name\Noter.xml</File>
<File>D:Project_Name\Noter.jar</File>
</Common>
<Project_Name>
<File>D:\Util.bat</File>
<File>D:\Util.xml</File>
<File>D:\log.bat</File>
</Project_Name>
</Noter>
<CCNET>
This the complete script for remove last N line
count the total line
set Line = Line - N , remain just processing lines number
#echo OFF
setlocal EnableDelayedExpansion
set LINES=0
for /f "delims==" %%I in (infile.txt) do (
set /a LINES=LINES+1
)
echo Total Lines : %LINES%
echo.
:: n = 5 , last 5 line will ignore
set /a LINES=LINES-5
call:PrintFirstNLine > output.txt
goto EOF
:PrintFirstNLine
set cur=0
for /f "delims==" %%I in (infile.txt) do (
echo %%I
::echo !cur! : %%I
set /a cur=cur+1
if "!cur!"=="%LINES%" goto EOF
)
:EOF
exit /b
Here call:PrintFirstNLine > output.txt will give the output in an external file name as output.txt
Output for sample Input
<Project_Name>
<CBA_Notifier>
<Common>
<File>D:\CBA\CBA_Notifier\Project_Name\IPS-Util.jar</File>
<File>D:\CBA\CBA_Notifier\Project_Name\Notifier.bat</File>
<File>D:\CBA\CBA_Notifier\Project_Name\Notifier.xml</File>
<File>D:\CBA\CBA_Notifier\Project_Name\Notifier.jar</File>
</Common>
<Project_Name>
<File>D:\CBA\CBA_Notifier\IPS-Util.bat</File>
remove last 5 line
Update
:PrintFirstNLine
set cur=0
for /F "tokens=1* delims=]" %%I in ('type "infile.txt" ^| find /V /N ""') do (
if "%%J"=="" (echo.) else (
echo.%%J
set /a cur=cur+1
)
if "!cur!"=="%LINES%" goto EOF
)
This script will takes 1 arguement, the file to be trunkated, creates a temporary file and then replaces the original file with the shorter one.
#echo off
setlocal enabledelayedexpansion
set count=
for /f %%x in ('type %1 ^| find /c /v ""') do set /a lines=%%x-5
copy /y nul %tmp%\tmp.zzz > nul
for /f "tokens=*" %%x in ('type %1 ^| find /v ""') do (
set /a count=count+1
if !count! leq %lines% echo %%x>>%tmp%\tmp.zzz
)
move /y %tmp%\tmp.zzz %1 > nul
If the original file is 5 or less lines, the main output routine will noT create a file. To combat this, I use the copy /y null to create a zero byte file.
If you would rather not have an empty file, just remove the copy /y nul line, and replace it with the following line:
if %lines% leq 0 del %1
You should use one method or the other, otherwise source files with 5 or less lines will remain untouched. (Neither replaced or deleted.)
to delete last lines from your file,
1 copy starting lines that are needed from file like from- e:\original.txt
2 paste them in new file like- e:\new\newfile1.txt
code is thanks to the person giving me this code:
remember all may be done if you have motive and even blood hb =6. but help of nature is required always as you are a part of it
#echo off & setLocal enableDELAYedeXpansion
set N=
for /f "tokens=* delims= " %%a in (e:\4.txt) do (
set /a N+=1
if !N! gtr 264 goto :did
e:\new4.txt echo.%%a
)
:did
if you have 800 files then use excel to make code for 800 and then copy it to notepad and using Ctrl+h replace space with no space. then rename file as haha.bat . run in folder with files numbered 1.txt 2.txt 3.txt etc. any enquirers welcome Erkamaldev#gmail.com " Long Live Bharata"
A slow method with less coding:
set input=file.txt
set remove=7
for /f "delims=" %i in ('find /c /v "" ^< "%cd%\%input%"') do set lines=%i
set /a lines-=remove
for /l %i in (1,1,!lines!) do findstr /n . log.txt | findstr /b %i:
May be redirected to a file.
Each line is prefixed with the line number; may be removed with extra coding.
A faster version with /g flag in my answer at:
How to split large text file in windows?
Tested in Win 10 CMD, on 577KB file, 7669 lines.