I'm using a scheduled task to run a batch file for exporting backups. Within the command for exporting it uses "FILE=filename". I gave it a name but how can I make it numbered so it doesn't overwrite? (e.g. file1, file2, file3).
Thanks
if you are in the same directory:
#echo off
setlocal enableDelayedExpansion
set "file_name_pattern=file"
for %%a in (file*) do (
set "file_name=%%~na"
)
set "last_file_number=!file_name:%file_name_pattern%=!"
echo last file number : !last_file_number!
set /a next_file_number=last_file_number
set next_file=!file_name_pattern!%next_file_number%
echo next file : %next_file%
endlocal
A solution with FOR /L
#echo off
setlocal enableDelayedExpansion
set "file_name_pattern=file"
set init=1
for /l %%n in (1;1;10000) do (
echo %%n
if not exist "!file_name_pattern!%%n" (
set last_file_number=%%n
goto :break_for
rem
)
)
:break_for
echo last file number : !last_file_number!
set /a next_file_number=last_file_number+1
set next_file=!file_name_pattern!%next_file_number%
echo next file : %next_file%
endlocal
Related
I need to move few files from one folder to sub folder. My folder structure is already ready.
File current folder: D:\AB\*.*
The file name is: SS-AA-Report-Temp File for Script Testing-Daily-31March.txt
Destination folder: D:\AB\Pm 1.1 File For Script\Daily\
How to check file name substring with folder name substring and move?
Note I have multiple files like this.
set Path1= d:\AB
Pushd %Path1%
echo %Path1%
for %%i in (*.*) do SET "FName=%%~ni"
For /F "Tokens=4-5 Delims=-" %%A In ("%FName%") Do (
Set "FoldOne=%%A"
Set "FoldTwo=%%B"
)
echo out %RDate%
mkdir %Path1%\"%FoldOne%"\"%FoldTwo%"\%RDate%
move %Path1%\"%FName%".* %Path1%\"%FoldOne%"\"%FoldTwo%"\%RDate%\
Edit:
File names format:
A-A-Format-Here First connectivity install on Day 0 regurlarly-Daily-All-2017-03-27-09-31-16.xls
A-A-Format-Already First connectivity with 10 days created-Weekly-All-2016-11-28-10-01-02.csv
A-A-Report-withname 1.2 Sample Report (Network Plan Report)-Daily-Detail-2017-01-03-23-53.xls
A-A-Report-Nextreport 1.2 Sample Report (Network Plan Report)-Weekly-Detail-2017-01-03-23-02-53.csv
Now my folder structure is:
D:\AB\Pm 1.1 First connectivity install on Day 0\Daily\05042017
D:\AB\Pm 2.1 First connectivity with 10 days\Weekly\29032017
D:\AB\Pm 1.2 Sample Report\Daily\05042017
D:\AB\Pm 1.2 Sample Report\Weekly\29032017
And here is the batch file I have already:
set Path1= d:\AB
Pushd %Path1%
echo %Path1%
for %%i in (*.*) do SET "FName=%%~ni"
For /F "Tokens=4-5 Delims=-" %%A In ("%FName%") Do (
Set "FoldOne=%%A"
Set "FoldTwo=%%B"
)
echo 1 %FoldOne%
echo 3 %FoldTwo%
IF %FoldTwo% == Daily (
echo here Daily
For /F UseBackQ %%A In (
`PowerShell "(Get-Date).AddDays(-1).ToString('ddMMyyyy')"`
) Do (Set "RDate=%%A"
echo ffor %RDate%
)
)
IF %FoldTwo% == Weekly (
Echo Weekly
For /F UseBackQ %%A In (
`PowerShell "(Get-Date).AddDays(-7).ToString('ddMMyyyy')"`
) Do (Set "RDate=%%A"
echo %RDate%
)
)
mkdir %Path1%\"%FoldOne%"\"%FoldTwo%"\%RDate%
move %Path1%\"%FName%".* %Path1%\"%FoldOne%"\"%FoldTwo%"\%RDate%\
Pushd d:\
GoTo :EOF
The logic for matching file name substrings with folder name is still very fuzzy.
However, I coded two possible solutions doing both the same using partly different methods.
The first complete batch code:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
cd /D "D:\AB"
rem Get name of each subfolder starting with string Pm, a space, two single
rem digit numbers separated by a dot, one more space and more characters to
rem indexed environment variables for later usage. And assign the substring
rem after the first 7 characters of each folder name also to an index
rem environment variable.
set FolderIndex=0
for /D %%I in ("Pm ?.? *") do (
set "FolderName!FolderIndex!=%%I"
set "CurrentPath=%%I
set "FolderPart!FolderIndex!=!CurrentPath:~7!"
set /A FolderIndex+=1
)
set "FolderCount=%FolderIndex%"
rem set Folder
rem Get date of yesterday and date of a week ago.
for /F "usebackq" %%I in (`PowerShell.exe "(Get-Date).AddDays(-1).ToString('ddMMyyyy')"`) do set "DateDaily=%%I"
for /F "usebackq" %%I in (`PowerShell.exe "(Get-Date).AddDays(-7).ToString('ddMMyyyy')"`) do set "DateWeekly=%%I"
rem set Date
rem Process now each file matching the wildcard pattern below in
rem current folder and calling a subroutine with current file name.
set "FileNotMoved=0"
for %%I in (*-*-*-*-*) do call :MoveToFolder "%%I"
endlocal & if not %FileNotMoved% == 0 pause
goto :EOF
rem This subroutine first gets fourth and fifth dash delimited part from
rem each passed double quoted file name.
rem Then it replaces in each fourth file name part each folder name part
rem by an empty string until either all folder name parts are processed
rem or the string substitution was successful meaning the file name part
rem really contains the folder name part.
rem Note: The substitution does not work correct if any folder name part
rem contains an equal sign as this character is the delimiter
rem between string to find and replace string for substitution.
rem In second case with substitution being successful the folder for
rem the file could be determined and the file is moved to the found
rem folder if also time part could be determined from file name.
:MoveToFolder
for /F "tokens=4,5 delims=-" %%A in ("%~1") do set "NamePart=%%A" & set "NameTime=%%B"
set "FolderIndex=0"
:FindFolder
if %FolderIndex% == %FolderCount% (
set "FileNotMoved=1"
echo Found no folder for: %1
goto :EOF
)
call set "CurrentPart=%%FolderPart%FolderIndex%%%"
if "!NamePart:%CurrentPart%=!" == "!NamePart!" (
set /A FolderIndex+=1
goto FindFolder
)
call set "CurrentFolder=%%FolderName%FolderIndex%%%"
if /I "%NameTime%" == "Daily" (
set "FolderTime=%DateDaily%"
) else if /I "%NameTime%" == "Weekly" (
set "FolderTime=%DateWeekly%"
) else (
set "FileNotMoved=1"
echo Undefined time for: %1
goto :EOF
)
mkdir "%CurrentFolder%\%NameTime%\%FolderTime%" 2>nul
move "%~1" "%CurrentFolder%\%NameTime%\%FolderTime%\" >nul
if errorlevel 1 (
set "FileNotMoved=1"
echo Failed to move file: %1
)
goto :EOF
The second batch code differs from first solution only on how subroutine MoveToFolder is coded for finding the corresponding folder for current file name. For that reason just the code of the subroutine is posted below.
:MoveToFolder
for /F "tokens=4,5 delims=-" %%A in ("%~1") do set "NamePart=%%A" & set "NameTime=%%B"
for /F "tokens=1* delims==" %%X in ('set FolderPart') do (
if not "!NamePart:%%Y=!" == "%NamePart%" (
set "FolderName=%%X"
goto FoundFolder
)
)
set "FileNotMoved=1"
echo Found no folder for: %1
goto :EOF
:FoundFolder
if /I "%NameTime%" == "Daily" (
set "FolderTime=%DateDaily%"
) else if /I "%NameTime%" == "Weekly" (
set "FolderTime=%DateWeekly%"
) else (
set "FileNotMoved=1"
echo Undefined time for: %1
goto :EOF
)
set "FolderIndex=%FolderName:~10%"
call set "CurrentFolder=%%FolderName%FolderIndex%%%"
mkdir "%CurrentFolder%\%NameTime%\%FolderTime%" 2>nul
move %1 "%CurrentFolder%\%NameTime%\%FolderTime%\" >nul
if errorlevel 1 (
set "FileNotMoved=1"
echo Failed to move file: %1
)
goto :EOF
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
cd /?
echo /?
endlocal /?
for /?
goto /?
if /?
mkdir /?
move /?
pause /?
rem /?
set /?
setlocal /?
Read also the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul and >nul and answer on question Single line with multiple commands using Windows batch file for meaning of operator & on Windows command lines.
I was looking for some help in setting up a batch script to go through an entire directory and copy all .sql files to a single folder. I can do this easy enough with a FOR loop but I hit a snag if two or more files in different directories have the same name. I'm attempting to get around this using a counter but I'm having trouble getting it to be specific to individual file names.
My code so far:
set /A n=0
for /R %source% %%G in (*.sql) do (
if exist %destination%\sql_files\%%~nxG (
set /A n+=1
set "full=%%G"
set "name=%%~nG"
set "ext=%%~xG"
setlocal enabledelayedexpansion
copy "!full!" "!destination!\sql_files\!name!(!n!)!ext!" >nul
endlocal
) else (
copy "%%G" "%destination%\sql_files\" >nul
)
)
For example if I have:
%source%\dir1\file1.sql
%source%\dir1\file2.sql
%source%\dir2\file1.sql
%source%\dir2\file2.sql
%source%\dir3\file1.sql
I end up with:
file1.sql
file1(1).sql
file1(3).sql
file2.sql
file2(2).sql
What I would like to see is:
file1.sql
file1(1).sql
file1(2).sql
file2.sql
file2(1).sql
I thought that my answer might lie in a subroutine but I can't quite figure out the logic to make that work. Any help is greatly appreciated.
Here is a script that does what you want. It relies on the fact that the target directory is initially empty:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "SOURCE=."
set "DESTINATION=..\sql_files"
set "PATTERN=*.sql"
set "TMPFILE=%TEMP%\%~n0_%RANDOM%.tmp"
rem // Create target directory, check whether it is empty:
2> nul md "%DESTINATION%"
(2> nul dir /B /A "%DESTINATION%\*.*" | > nul find /V "") && (
>&2 echo Target directory "%DESTINATION%" is not empty!
exit /B 1
)
rem /* Write list of files to temporary file; each line holds
rem the pure file name and the full path, separated by `:`: */
if not defined SOURCE set "SOURCE=."
> "%TMPFILE%" (
for /R "%SOURCE%" %%F in ("%PATTERN%") do (
echo :%%~nxF:%%~fF
)
)
rem // Read temporary file with lines sorted by file names:
set "PREV=:" & set /A "INDEX=0"
for /F "tokens=1,* delims=:" %%E in ('sort "%TMPFILE%"') do (
rem // Cache file name parts and full path:
set "FILE=%%E"
set "NAME=%%~nE"
set "EXT=%%~xE"
set "FULL=%%F"
rem // Compare current with previous file name:
setlocal EnableDelayedExpansion
if /I not "!FILE!"=="!PREV!" (
endlocal
rem // Reset index if names do not match:
set /A "INDEX=0"
) else (
endlocal
rem // Increment index if names do match:
set /A "INDEX+=1"
)
rem // Build new file nase name:
setlocal EnableDelayedExpansion
if !INDEX! GTR 0 (
set "NAME=!NAME!(!INDEX!)"
)
rem // Copy file and rename accordingly:
> nul copy "!FULL!" "!DESTINATION!\!NAME!!EXT!"
endlocal
rem // Cache processed file name:
set "PREV=%%E"
)
rem // Delete temporary file:
del "%TMPFILE%"
endlocal
exit /B
Context
I'm currently programming with batch files, to use a specific pdf tool only available for cmd.
Problem
I'm trying to run a for loop, which recursively cycles through a directory finding all *.pdf files. Excluding the pdf's inside folders named "Originals"
If the pdf file is in a parent folder named "Originals", then it must be skipped. Otherwise count the pdf file with the %counter% variable.
Example Directory Structure
C:\New folder\file (1).pdf
C:\New folder\file (2).pdf
C:\New folder\Sub_1\file (1).pdf
C:\New folder\Sub_1\file (2).pdf
C:\New folder\Sub_1\file (3).pdf
C:\New folder\Sub_2\file (4).pdf
C:\New folder\Sub_2\file (5).pdf
C:\New folder\Originals\file (1).pdf
C:\New folder\Originals\file (2).pdf
Example batch file - Find all pdf's (excluding Originals)
:: Example.bat
#echo off
set myDirectory=C:\New folder
:: Search through myDirectory to find all .pdf files (including subdirectories)
setlocal enableDelayedExpansion
for /R "%myDirectory%" %%G in (*.pdf) do (
set inputDirectory=%%~dpG
echo G = !%%G!
echo inputDirectory = !inputDirectory!
for /f "delims=\" %%F in ("!inputDirectory!") do (
set currentFolder=%%~nxF
echo currentFolder = !currentFolder!
)
if NOT "!currentFolder!"=="Originals" (
set /a count=count+1
)
)
echo There are %count% PDF's (excluding originals)
pause
Please run the example batch file to demonstrate what I have so far. Any help or solutions would be appreciated.
Cheers!
Solved
Here's what I came up with based on everyone's solutions!
#echo off
setlocal enabledelayedexpansion
set count=0
set myDirectory=C:\New folder
for /r "%myDirectory%" %%i in (*.pdf) do (
set inputDirectory=%%~dpi
set inputDirectoryNoSlash=!inputDirectory:~0,-1!
for %%j in (!inputDirectoryNoSlash!) do set sub=%%~nxj
if NOT !sub!==Originals (
set /a count=count+1
)
)
echo There are %count% PDF's (excluding originals)
pause
Thanks again guys!
Another similar method is:
#echo off
setlocal enabledelayedexpansion
set count=0
set dir=C:\TEST
echo %count%
for /r "%dir%" %%i in (*.pdf) do (
set dirx=%%~dpi
set con=!dirx:~0,-1!
for %%j in (!con!) do set sub=%%~nxj
if !sub!==Originals (
cls
) else (
set /a count=count+1
)
)
echo !count!
pause
*Change to appropriate pathname
%%~pG Expand %%G to a Path only including a trailing \ backslash. Undesired, clear it away as follows:
for /f "tokens=* delims=\" %%F in ("!inputDirectory:~0,-1!") do (
set currentFolder=%%~nxF
echo currentFolder = !currentFolder!
)
Try this:
#echo off
setlocal EnableDelayedExpansion
set myDirectory=C:\New folder
set count=0
for /F "delims=" %%a in ('dir /S "%myDirectory%\*.pdf" ^| findstr /V /L "\Originals\"') do (
echo File: %%a
set /A count+=1
)
echo There are %count% PDF's (excluding originals)
pause
I need batch script to copy all files from one directory to another and rename them all to a default name (ex. NAME54.pdf) and continue counting from destination`s maximum number in name.
I wrote some script but it seems not working:
#echo on
D:
set count=0
for %%a in (scans1\*.*) do (
set /a count+=1
)
set count1=0
for %%b in (scans\*.*) do (
set /a count1+=1
)
for /l %%c in (1,1,%count1%) do (
set /a count+=1
copy D:\scans\*.* D:\scans\NAME%count%.pdf
)
pause
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET /a count=0
for %%c in (%sourcedir%\*.*) do (
CALL :select
ECHO copy "%%c" "%destdir%\NAME!count!.pdf"
)
GOTO :EOF
:select
SET /a count+=1
IF EXIST "%destdir%\NAME%count%.pdf" GOTO select
GOTO :eof
I've set up distinct source and destination directories. You would need to change these names to suit your circumstances.
I've chosen to simply ECHO the required copy command so that you can see the resultant commands. You'd need to change ECHO copy to copy to actually execute the commands.
If you append >nul to the copy command, the 1 file(s) copied response will be suppressed.
I need to iterate over files contained in a folder and extract the first line for each file. I've tried to get this writing two batch file - the first one overate over files:
FOR %%a in (D:\TEST_BAT\*.TXT) do (
call Estrai_Header.bat %%a %header%
#echo on
echo %header%
)
The second one (named Estrai_header.bat) extract the first line for the file (just passing it as parameter):
set header = ""
SET /A maxlines=1
SET /A linecount=0
FOR /F %%b IN (%1) DO (
IF !linecount! GEQ %maxlines% GOTO ExitLoop
set $2 = %2%%b
echo %2%
SET /A linecount+=1
echo %linecount%
)
:ExitLoop
exit /b
Estrai_Header.bat works correctly and prints for every file just the first row. But I cannot see the value of the first line extracted in the first batch (it prints a void string). What's wrong in these batch files?
Thanks in advance.
try this:
#echo off&setlocal
FOR %%a in (D:\TEST_BAT\*.TXT) do (
set "line="
for /f "usebackqdelims=" %%i in ("%%a") do if not defined line set "line=%%i"
setlocal enabledelayedexpansion
echo(!line!
endlocal
)