I have created a batch file which should do several things, including appending all text documents of a certain format into one text file provided there are more than one text files of this format in the directory. This section of the code is below:
:multiple
SET /a count=0
ECHO.> "%location%\UAV_camera_coords_all.txt"
FOR /r "%location%\Output" %%G in ("UAV_camera_coords_*.txt") do set /a count+=1
IF %count% GTR 1 (
FOR /r "%location%\Output" %%G in ("*.txt") DO (
SET file=%%~G
TYPE "%file%">>"%location%\UAV_camera_coords_all"
)
GOTO :end
It seems that the code is crashing upon reaching the if statement even though the count variable is greater than one. None of the code in the if statement is executed and indeed none of the code which should come after the if statement is executed either. Is there any syntax or other error which may be causing this?
Besides my comment. I assume that you are not really planning on typing the output of *.txt but instead only UAV_camera_coords_*.txt.. if not, feel free to change it back to *.txt
#echo off
for /f "tokens=1,*" %%i in ('dir /s "%location%\UAV_camera_coords_*.txt" ^| findstr "File(s)"') do set cnt=%%i
if %cnt% gtr 1 (
for /f %%a in ('dir /b /s "%location%\UAV_camera_coords_*.txt"') do type "%%~a"
)>"%location%\UAV_camera_coords-all.txt"
Note, I changed the output filename to be -all and not _all as that would type the file onto itself if it was to be a txt file as well.
Edit adding back original answer, before I realised you were recursively searching through directories:
#echo off
for /f "tokens=1,*" %%i in ('dir "UAV_camera_coords_*.txt" ^| findstr "File(s)"') do if %%i gtr 1 type "UAV_camera_coords_*.txt">>"%location%\UAV_camera_coords_all"
Just for the purpose of providing an alternative, this one uses xcopy to check the file count, and copy to merge them.
PushD "%location%\Output" 2>NUL && For /F %%G In ('""%__AppDir__%xcopy.exe" "UAV_camera_coords_*.txt" . /SQL"')Do If %%G Gtr 1 Copy /Y /B "UAV_camera_coords_*.txt" "..\UAV_camera_coords_all.txt">NUL & PopD
Related
I have a bunch of .txt files:
1.txt containing string "1"
2.txt containing string "2"
3.txt containing string "3"
I need to combine them to get "result.txt" containing this:
1
2
3
I used echo. as a new line character in a batch:
for /r %%i in (*.txt) do (
type %%i>> result.txt
echo.>> result.txt
)
But in "result.txt" I'm getting this:
1
2.
3.
So, echo. actually works perfectly well for the first (1.txt) file, but it also puts a . before new lines for the rest of the files.
Can someone please fix batch code for me?
P.S.: the problem occurred because .txt files were located in different subfolders - that's why I used for /r initially (it doesn't always work, see details below!).
Thanks #Mofi, see his comments below the starting post!
This is a solution for а Folder on (any) user's Desktop:
for /f "delims=" %%i in ('dir "%UserProfile%\Desktop\Folder\*.txt" /a-d /b /on /s 2^>nul') do (
echo %%~fi>> result.txt
type "%%i">> result.txt
echo(>> result.txt
)
echo %%~fi>> result.txt adds full path to any *.txt file found in
that folder (and subfolders);
type "%%i">> result.txt merges found *.txt files
contents;
echo(>> result.txt is the new line character requested!
This code tested on NTFS and is promised to work on FAT\FAT32 etc. - unlike for /R (see #Mofi comments below the starting post!).
P.S.: you can launch this batch code from any location; also, use echo {anytext}>> result.txt after echo(>> result.txt to easily navigate between breaks in "result.txt" :)
P.P.S.: also, if you want to get rid of blank line in the EOF "result.txt" - use this:
set /a counter1=0
set /a counter2=0
::cycle 1
for /f "delims=" %%i in ('dir "%UserProfile%\Desktop\Folder\*.txt" /a-d /b /on /s 2^>nul') do (
set /a counter1+=1
)
::cycle 2
setlocal enableextensions enabledelayedexpansion
for /f "delims=" %%i in ('dir "%UserProfile%\Desktop\Folder\*.txt" /a-d /b /on /s 2^>nul') do (
echo %%~fi>> result.txt
type "%%i">> result.txt
set /a counter2+=1
if not !counter2!==%counter1% (echo(>> result.txt)
)
endlocal
Inspired by: https://stackoverflow.com/a/7522822/6859021
both cycles has the same for /f conditions;
::cycle 1 counts number of files that are about to undergo the procedure;
::cycle 2 is identical to original solution, except for "Inspired
by" details;
::* lines are comments: they don't affect code
execution;
if not !counter2!==%counter1% (echo(>> result.txt) merely puts echo( for all lines, except for the last one! :D
Notice however that counters will work properly only if "result.txt" will NOT be located inside Folder of interest, or it's subfolders.
First: I could not reproduce the problem where additional dots are added to the file.
However I found a different issue, that might have to do something with it. When you are iterating over all text-files, you get the result.txt at one point as well. (And other files you might add or change during runtime.)
So I created this basic script, which does exactly what you described as your desired behavior:
#echo off
:: clear
rd testdir /s /q 2>nul
:: create files
md testdir
cd testdir
for /l %%i in (1 1 3) do (
<nul set /p "=%%i">"%%i.txt"
)
:: combine the files
for /r %%f in (*.txt) do (
if not "%%~nf"=="result" (
type "%%f">>result.txt
echo.>>result.txt
)
)
:: show result
echo result.txt
type result.txt
pause
I am traversing folders on a drive, collecting file names with specific extensions, and building a string which is later used in a command line switch. When I find a qualifying file I need to know its full path as this is what is required by the command line. I currently use "%~dp0%%a\%%b" to build the full path, but I can see that may have limitations later on when the batch becomes more complex (e.g. it digs deeper into sub folders). I am hoping there is a way to replace "%~dp0%%a\%%b" with the path to the located file. Thank you:
#ECHO OFF
for /f "usebackq tokens=*" %%a in (`dir /b /a:d`) do (
pushd %%a
setlocal ENABLEDELAYEDEXPANSION
for /f "delims=" %%b in ('dir /b "*.E01" "*.L01" "*.AD1" 2^>nul') do (
SET EVIDENCE_STR=!EVIDENCE_STR! /e:"%~dp0%%a\%%b"
)
IF DEFINED EVIDENCE_STR (
ECHO !EVIDENCE_STR!
) ELSE (
ECHO No evidence files located in: %%a
)
endlocal
SET EVIDENCE_STR=
popd
)
PAUSE
Why do you need to create 2 loops, each running a dir command to find files? Why not just do for /R loop? Here is an example:
#echo off
set "files=*.E01 *.L01 *.AD"
for /R %%a in (%files%) do echo %%a
Simply use "Sub"-Option: /S of the DIR-Command:
Dir /B /S C:\*.jpg
cause it is that equivalent to:
#echo off
set "DirPath=C:\"
set "files=*.jpg"
for /R %DirPath% %%a in (%files%) do echo %%a
and so you should got the same result in each script.
The Problem: If you don't want any deep of SubDirectorys, you've to filter out these and so you may lose time - in both solutions.
I have some of log files formatted like this "name.log"
I would like to copy those from one folder to another folder like
xcopy /y "C:\Folder1" "D:\Folder2"
Adding I need to rename file with created date of original file (no copy file) so that the text file in Folder2 would be like "yyyymmddhhmm.log" if some file has the same name (date of creation) it will be overwritten.
I have a code with help of #Wes Larson but there is something wrong.
set Source=C:\Users\user1\Desktop\1
set Dest=C:\Users\user1\Desktop\2
if not exist %Dest% md %Dest%
for /F %%a in ('dir /b "%Source%\*.txt"') do call :Sub %%a
goto :eof
:Sub
set "filename=%1"
for /F %%s in ("%Source%\%1") do if %%~zs==0 goto :eof
set "datepart="
FOR /F "tokens=1-5 delims=/-: " %%a IN ('dir /tc "%filename%" ^| findstr "%filename%"') DO (
IF "%%c" neq "" SET "datepart=%%c%%a%%b%%d%%e"
)
FOR /F %%a IN ("%filename%") DO (
set "NewName=%%~na %datepart%%%~xa"
)
xcopy /y "%Source%\%filename%" "%Dest%\%NewName%*"
GOTO :EOF
The problem is that If I don't put the .bat in the same folder that origin files (Folder1),some files aren't change name. For example, if it is out some files change name with old name and one white space. The command windows tell me that it doesn't find the file when it get the creation date. It's very strange because some files are copied well.
What do I need to solve this problem?
Before we get to an answer: When troubleshooting/debugging batch scripts, don't use #echo off. It's great once you have it working the way you want, but comment it out when you need to see what your code is doing line by line. Also, you'll want to open a cmd window and run your script from a command line, so the window doesn't close as soon as your script finishes.
Now on to your code. This for loop is part of your problem:
FOR /f "tokens=1-3delims=/-:" %%a IN ('dir /tc "%filename%"') DO IF "%%c" neq "" SET "datepart=%%a-%%b-%%c"
Firstly, you haven't set %filename%, so this loop will fail. You should probably have a line in your :Sub like this:
set "filename=%1"
Now, assuming that %filename% is fixed, by the time this loop has finished, your %%a, %%b, and %%c variables have been set to the values in the last line of output from the command 'dir /tc "%filename%"', which is something like X Dir(s) XXX,XXX,XXX,XXX bytes free, and isn't the information you're looking for.
So, instead, you can tweak it a little so that you pipe the output of dir to findstr, looking for just the one, single line that you want to use, like this:
FOR /f "tokens=1-3delims=/-:" %%a IN ('dir /tc "%filename%" ^| findstr "%filename%"') DO (
IF "%%c" neq "" SET "datepart=%%a-%%b-%%c"
)
But then, you have another problem: your %datepart% looks like MM-DD-YYYY hh. This is because you changed your delims from the default (which includes spaces and tabs), to only the specified characters. Also, from your question, you want to also include hour and minute all formatted as "yyyymmddhhmm.log" , which means you'll need those next two tokens, too. Then your line becomes this:
FOR /f "tokens=1-5 delims=/-: " %%a IN ('dir /tc "%filename%" ^| findstr "%filename%"') DO (
IF "%%c" neq "" SET "datepart=%%c%%a%%b%%d%%e"
)
Next, your nested for loop is confusing, unnecessary, and causing problems:
FOR /f %%a IN ("%filename%") DO FOR /f %%d IN ("%datepart%") DO (
set NewName="%%~na %%d%%~xa
xcopy e/d/y "%Source%\%OrgName%" "%Dest%\%NewName%"
)
You already have the %datepart% variable, and you don't need to turn it into one of the for %%d variables to be able to reference it. So it becomes much simpler when you do it like this:
FOR /f %%a IN ("%filename%") DO (set "NewName=%%~na %datepart%%%~xa")
Also, because you run into delayed expansion issues, it's simpler to take the xcopy command out of the loop.
And once again, you have a variable %OrgName% that you never set. Fortunately, this is actually unnecessary as you already have the original file name captured as %filename%. So your overly complicated nested for loop becomes this:
FOR /f %%a IN ("%filename%") DO (
set "NewName=%%~na %datepart%%%~xa"
)
echo xcopy e/d/y "%Source%\%filename%" "%Dest%\%NewName%"
Im trying to copy css files from IE's cache folder to some folder in C:
The thing is theres lots of duplicates but I want to keep them all, so I made a batch script to copy all css files and add a counter/index variable to the beginning of each file. The problem is the variable is not incrementing and I dont know why? This is my script:
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /a c=0
for /f "tokens=*" %%A in ('dir /b /s /a-d "C:\Users\%username%\AppData\Local\Microsoft\Windows\Temporary Internet Files\Content.IE5\*.css"') do (
set /a c=c+1
copy "%%A" "C:\Target\%c%_%%~nxA"
)
endlocal
Instead of some 30 css files being copied (I know this cuz I can see them in IE's cache folder) Im getting only about 10 copied and they just have "0_" appended at the front instead of an incrementing number (1-infinity).
I also tried !c! instead of %c% in the copy line part but it just adds literally "!c!" instead of the variables' value.
What am I doing wrong here?
Not as fast (one dir per file copy), but get independent numeration for each css file
set source=C:\Users\%username%\AppData\Local\Microsoft\Windows\Temporary Internet Files\Content.IE5
for /f "tokens=*" %%A in ('dir /b /s /a-d "%source%\*.css"') do (
for /f %%C in ('dir /b "c:\target\*_%%~nxA" ^| find /c "_"') do (
copy "%%A" "c:\target\%%C_%%~nxA"
)
)
You did set enabledelayedexpansion but you are not using it in your loop. You should give this a try, this is what worked for me:
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /a c=0
for /f "tokens=*" %%A in ('dir /b /s /a-d "C:\Users\%username%\AppData\Local\Microsoft\Windows\Temporary Internet Files\Content.IE5\*.css"') do (
set /a c=c+1
copy "%%A" "C:\Target\!c!_%%~nxA"
)
endlocal
The only difference is line 6 where I changed %c% to !c!.
Can anyone help me create a batch file? Basically, my goal is to create a batch file that will keep the LATEST 7 .txt files (in other words, the newest) in the folder and subsequently delete the rest. That's IF there are more than 7 files in the folder.
The problem I'm having right now is the fact that the batch file that I have created deletes most of the files because their date is from a month or two or so. I want to keep the latest 7 files at all times no matter how old they are.
So this is what I have -
#echo off
setlocal enableextensions
rem ********************************************************************************
rem ******************************* LOCAL VARIABLES ******************************
rem ********************************************************************************
SET TargetDirectory="C:\TEMP\test"
SET No_of_fles_to_keep=7
SET count=0
set cnt=0
rem ********************************************************************************
cd /d %TargetDirectory%
REM timeout /T 500
for %%x in (*) do set /a count+=1
for %%A in (*.bat) do set /a cnt+=1
cd /d %TargetDirectory%
REM timeout /T 500
IF %count% gtr %No_of_fles_to_keep% forfiles -p %TargetDirectory% -s -m "*.txt" -d -%No_of_fles_to_keep% -c "cmd /c del #path"
echo %count%
echo File count = %cnt%
Any help is appreciated.
You can use DIR with /O-D to list the text files in descending timestamp order. FOR /F allows you to iterate over each file. SET /A is used to keep track of how many files have been listed so far. Now comes the tricky part.
Within a code block you normally need to use delayed expansion to work with the value of a variable that was set earlier in the same block. But delayed expansion can cause problems in a FOR loop if the FOR variable value contains !, and ! is valid in file names. I get around the problem by using SET /A to intentionally divide by 0 when the 7th file name has been read. This raises an error that causes the conditional code to execute that undefines the KEEP variable. From that point on, all remaining files are deleted.
#echo off
setlocal
set /a cnt=0
set "keep=7"
for /f "eol=: delims=" %%F in ('dir /b /o-d /a-d *.txt') do (
if defined keep (
2>nul set /a "cnt+=1, 1/(keep-cnt)" || set "keep="
) else del "%%F"
)
Update
Oh my goodness, I just realized there is a trivial solution. Just use the FOR /F SKIP option to ignore the first 7 entries after sorting by last modified date, descending.
for /f "skip=7 eol=: delims=" %%F in ('dir /b /o-d /a-d *.txt') do #del "%%F"
You don't even need a batch file. Just change %% to % if run from the command prompt.
The Batch file below use a simpler approach. It use findstr /N "^" command to number each file, then it just compare each number to keep first seven files and delete the rest...
#echo off
for /f "tokens=1* delims=:" %%a in ('dir /b /o-d *.txt ^| findstr /N "^"') do (
if %%a gtr 7 del "%%b"
)
Antonio
If you don't write DOS scripts frequently which I don't, here is a summation of what others noted.
Other examples here will need the batch file in the same folder that you're deleting from.
To delete from another path: (Notice you have to add the path twice to the search and to the delete)
SET targetDir="C:\Test\Files\"
for /f "skip=7 eol=: delims=" %%F in ('dir /b /o-d /a-d %targetDir%*.txt') do #del "%targetDir%""%%F"
Thanks #dbenham, #SmileyFace, #user2924127 and all others who helped bring the answers.
This will keep 7 latest .txt files and remove all other .txt files
Execute below command in same directory from which you want to delete files
On command prompt
for /f "skip=7 eol=: delims=" %F in ('dir /b /o-d /a-d *.txt') do #del "%F"
Inside batch script
for /f "skip=7 eol=: delims=" %%F in ('dir /b /o-d /a-d *.txt') do #del "%%F"