Batch script for copying and renaming files - batch-file

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.

Related

Rename .txt files to first line in file and add "()" to duplicates

I am trying to rename 200+ .txt files in a directory with first line of their contents. The files contains IP address in format such as 12.345.678.90. I have found a batch-file which does exactly that, except that the duplicates don't get renamed at all.
I have edited (to my needs), and tested following script on Server2016 and Windows10 Which renames the files but doesn't do anything for duplicates.
#echo off
setlocal EnableDelayedExpansion
rem Multi-thread file rename program
if "%1" equ "Thread" goto ProcessBlock
rem Create the list of file names and count they
cd C:\Renamed_Files
set numFiles=0
(for %%f in (*.txt) do (
echo %%f
set /A numFiles+=1
)) > fileNames.tmp
rem Get number of threads and size of each block
set numThreads=%1
if not defined numThreads (
set /A numThreads=1, blockSize=numFiles
) else (
set /A blockSize=numFiles/numThreads
)
rem Create asynchronous threads to process block number 2 up to numThreads
if exist thread.* del thread.*
for /L %%t in (2,1,%numThreads%) do (
echo %time% > thread.%%t
start "" /B "%~F0" Thread %%t
)
rem Process block number 1
set count=0
for /F "delims=" %%f in (fileNames.tmp) do (
set /p line1=<%%f
ren "%%f" "!line1:~0,40!.txt"
set /A count+=1
if !count! equ %blockSize% goto endFirstBlock
)
:endFirstBlock
rem Wait for all asynchronous threads to end
if exist thread.* goto endFirstBlock
rem Delete the auxiliary file and end
del fileNames.tmp
goto :EOF
rem Process blocks 2 and up (asynchronous thread)
:ProcessBlock
set /A skip=(%2-1)*blockSize, count=0
for /F "skip=%skip% delims=" %%f in (fileNames.tmp) do (
set /p line1=<%%f
ren "%%f" "!line1:~0,40!.txt"
set /A count+=1
if !count! equ %blockSize% goto endBlock
)
:endBlock
del thread.%2
exit
I am hoping to rename .txt files and add () with a number of duplication so the duplicates can still get renamed with the same batch file, (by editing it of course), or a new batch would be needed? any suggestion? or new code is welcome.
Eventually duplicate files can be merged in to one, (as they would be containing the same ip addresses anyway), and then renamed the file to their first line of the content.
With multiple threads, you might have a race condition leading to a collision. The way I would start this is to use the thread number to avoid collisions. I am showing untested example code. Due to the difficulties with parentheses in DOS, I am instead going to use periods and recommend the same to you:
...
:ProcessBlock
set /A skip=(%2-1)*blockSize, count=0
for /F "skip=%skip% delims=" %%f in (fileNames.tmp) do call :ProcessBlockLoop "%%~f" %2
goto :eof
:ProcessBlockLoop
set /p line1=<"%~1"
set "filename=!line1:~0,40!"
:: Check for an existing file.
if not exist "%filename%.txt" goto :ProcessBlockLoopContinue
:: if we get here then there is an existing file.
set DupCnt=1
:ProcessBlockFilenameLoop
if not exist "%filename%.%2.%DupCnt%.txt" (
set filename=%filename%.%2.%DupCnt%
goto :ProcessBlockLoopContinue
)
:: increment our duplicate counter and try again
set /a DupCnt += 1
goto :ProcessBlockFilenameLoop
:ProcessBlockLoopContinue
:: Try the rename. If the rename fails, then reset the variables and loop again.
:: A retry counter should be added to avoid an infinite loop.
ren "%%f" "%filename%.txt" || set DupCnt=1&&set "filename=!line1:~0,40!"&&goto :ProcessBlockFilenameLoop
:: If we're here, the rename should have worked. You could double check again if desired.
set /A count+=1
if %count% equ %blockSize% (
del thread.%2
exit
)
goto :eof

Intuitive file sorting in batch scripts?

So in Windows Explorer, I have these files sorted like this:
I have this script to remove the brackets and one zero, and in case the trailing number is greater than or equal to 10, to remove two zeroes:
cd C:\folder
setlocal enabledelayedexpansion
SET /A COUNT=0
for %%a in (*.jpg) do (
SET /A COUNT+=1
ECHO !COUNT!
set f=%%a
IF !COUNT! GTR 9 (
set f=!f:^00 (=!
) ELSE (
set f=!f:^0 (=!
)
set f=!f:^)=!
ren "%%a" "!f!"
)
pause
However, once I run the code, I get this result:
So the batch file isn't going through the files "intuitively" like Windows Explorer shows them. Is there any way to change this? Or is there a better way to rename these files altogether?
This uses a different approach:
#echo off
cd C:\folder
setlocal enabledelayedexpansion
SET /A COUNT=0, REMOVE=2
for /F "delims=(" %%a in ('dir /B *.jpg') do (
SET /A COUNT+=1
ECHO !COUNT!
set "f=%%a"
IF !COUNT! EQU 10 SET "REMOVE=3"
for /F %%r in ("!REMOVE!") do set "f=!f:~0,-%%r!"
ren "%%a" "!f!!COUNT!.jpg"
)
pause
Here is a method that does not depend on the sort order used by the file system, preserving the numbers as occurring in the original file names.
For each file name (for instance, test_this_01 SELR_Opening_00000 (1).jpg), the portion after the last under-score _ is retrieved (00000 (1)). Then the parentheses and the space are removed and then the length is trimmed to five characters (00001). This string replaces the original one in the file name finally (test_this_01 SELR_Opening_00001.jpg); the file name must not contain the replaced portion (00000 (1)) multiple times (hence file names like this should not occur: test_this_00000 (1) SELR_Opening_00000 (1).jpg):
#echo off
setlocal DisableDelayedExpansion
rem // Define constants here:
set "LOCATION=."
set "PATTERN=*_* (*).jpg"
set /A "DIGITS=5"
pushd "%LOCATION%" || exit /B 1
for /F "usebackq eol=| delims=" %%F in (`
dir /B /A:-D /O:D /T:C "%PATTERN%"
`) do (
set "FILE=%%F"
setlocal EnableDelayedExpansion
set "LAST="
for %%I in ("!FILE:_=","!") do (
set "LAST=%%~nI" & set "FEXT=%%~xI"
set "FNEW=!FILE:%%~I=!"
)
set "LAST=!LAST:(=!" & set "LAST=!LAST:)=!"
set "LAST=!LAST: =!" & set "LAST=!LAST:~-5!"
ECHO ren "!FILE!" "!FNEW!!LAST!!FEXT!"
endlocal
)
popd
endlocal
exit /B
Adapt the directory location and the file search pattern in the top section of the script as you like.
After having tested, remove the upper-case ECHO command in order to actually rename files.

Rename with bat file from an specific number

I have a bat file that rename all of the png files to data_ files. It starts from data_1 and data_2 .... I want to start with data_140 and data_141...
How to do that?
:: Renaming files
for %%a in (*.png) do (
set /a count+=1
set "fname=%%~a"
setlocal enabledelayedexpansion
ren "!fname!" data_!count!.png
endlocal
)
I don't see the problem. SET /A count+=1 starts with count=0 as it's not defined yet. If you want your script to start at 140 just do set count=139 before you enter the loop:
:: Renaming files
set count = 139
for %%a in (*.png) do (
set /a count+=1
set "fname=%%~a"
setlocal enabledelayedexpansion
ren "!fname!" data_!count!.png
endlocal
)

Batch File - loop incrementing count in value not displaying correctly

I'm trying to read a file and output the lines of data into registry keys. The data collection works, but I don't understand the syntax required to increment the string values in the last loop.
#echo OFF
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq skip=1 delims=" %%a in (`"findstr /n ^^ C:\GetSID.txt"`) do (
set "var=%%a"
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!" This removes the prefix
echo(!var:~76,63!>>C:\SIDoutput.txt
goto :EndLoop
)
:EndLoop
set /p SID= <C:\users\paintic\SIDoutput.txt
set KEY_NAME="HKEY_USERS\!SID!\Software\Microsoft\Windows NT\CurrentVersion\PrinterPorts"
set Counter=1
for /f %%x in (C:\users\paintic\Networkprinters.txt) do (
set "Line_!Counter!=%%x"
set /a Counter+=1
if !Counter!==3 (Echo %line_counter%)
)
set /a counter2=!counter!-3
set counter=1
The part below is what I can't get to work. I'm trying to write LINE_1, LINE_2 and LINE_3 values from the previous loop to increment via the loop below. So VALUENAME should equal LINE_1, TYPE should = LINE_2's value and DATA should = LINE_3 on the first run and keep going up by 1 until the loop finishes (end of the file read)
`for /L %%i in (1,1,%counter2%) do (
set ValueName=%Line_!counter!%
set /a counter+=1
set Type=%Line_!counter!%
set /a Counter+=1
set Data=%Line_!counter!%
set /a Counter+=1
echo !ValueName!
echo !Type!
echo !Data!
REG ADD %KEY_NAME% /v !ValueName! /t !Type! /d !Data! /f
)
ENDLOCAL
Pause`
On searching for errors in batch file it is always helpful to use in first line #echo on or remove #echo off or comment this line with rem to see what cmd.exe really executes.
Command line interpreter fails on lines with set VariableName=%Line_!counter!% as the interpreter does not know what to expand first. I think it is not possible to create dynamically the name of an environment variable and reference next the value of this environment variable. This approach most likely does not work ever.
However, what you want to achieve can be done much easier directly in second loop as the following example demonstrates:
#echo off
setlocal EnableDelayedExpansion
rem Create data for demo example.
set "KEY_NAME=HKEY_USERS\S-1-5-20\Software\Microsoft\Windows NT\CurrentVersion\PrinterPorts"
echo TestValue>"%TEMP%\Networkprinters.txt"
echo REG_SZ>>"%TEMP%\Networkprinters.txt"
echo Sample Data>>"%TEMP%\Networkprinters.txt"
echo AnotherValue>>"%TEMP%\Networkprinters.txt"
echo REG_DWORD>>"%TEMP%\Networkprinters.txt"
echo ^1>>"%TEMP%\Networkprinters.txt"
rem Now the loop follows which reads the data from the file line
rem by line and build the line for using command "reg.exe" to
rem add the data to registry of the user with the defined SID.
set Counter=1
for /f "usebackq delims=" %%x in ("%TEMP%\Networkprinters.txt") do (
if "!Counter!"=="1" (
set "ValueName=%%x"
) else if "!Counter!"=="2" (
set "ValueType=%%x"
) else (
set "ValueData=%%x"
rem Echo the command instead of really executing "reg.exe".
echo reg.exe ADD %KEY_NAME% /v "!ValueName!" /t !ValueType! /d "!ValueData!" /f
set Counter=0
)
set /a Counter+=1
)
rem Delete the text file created for demo example.
del "%TEMP%\Networkprinters.txt"
endlocal
This solution is much easier than what you have tried and can be maybe even more simplified.

Batch Scripting iterating over files in a folder and extract for each one just the first line

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
)

Resources