Hi I am trying to copy all text files from a directory to another using a batch file. If in case the directory contains any sub folder the program must also parse the subfolder and copy the text file from folder and sub folder. If the files have the same name in the target folder(dTarget) rename the file before copying.
Following Is the code used
#echo off &setlocal
set "dSource=c:\test\a"
set "dTarget=c:\test\op"
set "fType=*.txt"
for %%i in ("%dSource%\%fType%") do if not exist "%dtarget%\%%~nxi" (copy /b "%%~i" "%dtarget%") else call :process "%%~i"
goto :eof
:process
set /a cnt=-1
:loop
set /a cnt+=1
set "fname=%dtarget%\%~n1(%cnt%)%~x1"
if exist "%fname%" goto :loop
copy /b "%~1" "%fname%"
goto :eof
endlocal
This program Works fine if there exist no subdirectory, I tried to use /R but of no use, only the directory files are copied. Any help would be appreciated.
This should work:
#echo off &setlocal
set "dSource=c:\test\a"
set "dTarget=c:\test\op"
set "fType=*.txt"
DIR /A:D /B %dSource% > folders.txt
for /f %%G in (folders.txt) do for %%i in ("%dSource%\%%G\%fType%") do if not exist "%dtarget%\%%~nxi" (copy /b "%%~i" "%dtarget%") else call :process "%%~i"
goto :eof
:process
set /a cnt=-1
:loop
set /a cnt+=1
set "fname=%dtarget%\%~n1(%cnt%)%~x1"
if exist "%fname%" goto :loop
copy /b "%~1" "%fname%"
goto :eof
endlocal
This is another method which should succeed:
#echo off
setlocal enabledelayedexpansion
for /r %%a in (*.txt) do copy /-Y "%%a" "d:\target\folder\%%~na - !random!!random!%%~xa"
Related
I have a folder containing several hundred sub-folders in the format Name, ID. Each of these folders contain several sub folders, some of which contain spaces in their names. I would like to rename only the sub folders and not the parent folders by replacing the spaces with underscores, e.g. C:\Location\John, 1234\My Documents to C:\Location\John, 1234\My_Documents.
I have tried modifying a piece of script I have found on here but it changes the parent folder as well
Here is the unedited code:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "StartFolder=C:\Tydelik"
cd /D %SystemRoot%
set "RenameError="
rem Rename all folders containing at least one space character in folder name.
for /F "delims=" %%I in ('dir "%StartFolder%\* *" /AD /B /S 2^>nul') do call :RenameFolder "%%I"
if defined RenameError echo/& pause
rem Restore initial environment and exit this batch file.
endlocal
goto :EOF
:RenameFolder
set "NewFolderName=%~nx1"
set "NewFolderName=%NewFolderName: =_%"
set "FolderPath=%~dp1"
if not exist "%FolderPath%" set "FolderPath=%FolderPath: =_%"
set "FullFolderName=%FolderPath%%~nx1"
if not exist "%FullFolderName%\" set "RenameError=1" & goto :EOF
for %%J in ("%FullFolderName%") do set "FolderAttributes=%%~aJ"
if "%FolderAttributes:~3,1%" == "h" %SystemRoot%\System32\attrib.exe -h "%FullFolderName%"
ren "%FullFolderName%" "%NewFolderName%" 2>nul
if errorlevel 1 goto ErrorFolderRename
if "%FolderAttributes:~3,1%" == "h" %SystemRoot%\System32\attrib.exe +h "%FolderPath%%NewFolderName%"
goto :EOF
:ErrorFolderRename
echo Error renaming folder "%FullFolderName%"
set "RenameError=1"
if "%FolderAttributes:~3,1%" == "h" %SystemRoot%\System32\attrib.exe +h "%FullFolderName%"
goto :EOF
As I said the expected output for each sub folder should be C:\Location\John, 1234\My_Documents instead of C:\Location\John, 1234\My Documents. Currently with the code I have, I get C:\Tydelik\John,_1234\My_Documents.
While Compo's solution renames folders "depth=2", this renames just the "leafes" (very last folders of a tree, "depth=last"). I kept your call approach to avoid delayed expansion and resulting possible problems (folder names with ! - unlikely in your situation, but one never knows...)
#echo off
setlocal
set "sourcedir=..\..\"
for /f "delims=" %%I in ('dir "%sourcedir%" /ad /b /s 2^>nul') do call :RenameFolder "%%I"
goto :eof
:RenameFolder
dir /ad /b /s "%~1" 2>nul | find /v "" >nul && goto :eof ::skip renaming, if a subfolder exists
set "leaf=%~nx1"
ECHO ren "%~1" "%leaf: =_%"
goto :eof
Note: for security reasons I disabled the ren command by just echoing it. If it works as intended, remove the ECHO.
Here's an example of what I think you're looking for, based upon the fact that you're interested only in renaming subdirectories of "C:\Tydelik\Name, ID", not any contained within those subdirectories:
#Echo Off
SetLocal DisableDelayedExpansion
Set "SourceDir=C:\Tydelik"
For /F "EOL=?Delims=" %%A In ('Dir /B/AD "%SourceDir%" 2^>NUL'
)Do Set "TargetDir="&For /F "EOL=?Delims=" %%B In (
'Dir /B/AD "%SourceDir%\%%A" 2^>NUL') Do (Set "TargetDir=%%B"
SetLocal EnableDelayedExpansion
If Not "!TargetDir: =!"=="!TargetDir!" (
Ren "%SourceDir%\%%A\%%B" "!TargetDir: =_!")
EndLocal)
I have the following code to search for a specific file name (ratings.zil) across multiple folders and copy them to a new folder:
for /R %f in (ratings.zil) do #IF EXIST %f copy "%f" "C:\here"
But when the file copies to the new folder it overwrites instead of appending a number at the end of each ratings.zil – i.e. ratings(1).zil, ratings(2).zil. Is there a way to add a loop to the above code that will append a number after each file?
This question was originally marked as a duplicate, except the answer for the duplicate only works when you’re copying a file within the same folder.
Here is a slightly ammended version of DBenhams answer.
#echo off
setlocal disableDelayedExpansion
if "%~2" equ "" echo Error: Insufficient arguments>&2&exit /b 1
set "source=%~f1"
set "target=%~f2"
md "%target%"
set /a cnt=0
for /r "%source%" %%F in (ratings.zil) do if "%%~dpF" neq "%target%\" (
if exist "%%F" (
if exist "%target%\%%~nxF" (
set /a cnt+=1
set "full=%%F"
set "name=%%~nF"
set "ext=%%~xF"
setlocal enableDelayedExpansion
copy "!full!" "!target!\!name!(!cnt!)!ext!" >nul
endlocal
) else copy "%%F" "%target%" >nul
)
)
In order to run this, you need to save the file as something like myRename.cmd then simply open cmd.exe and run it as:
myRename.cmd "C:\Source of files" "D:\Destination"
If you perfer to place this in a set directory and have a static destination folder and be able to just double click it, then this will do:
#echo off
setlocal disableDelayedExpansion
set "target=C:\here"
md "%target%"
set /a cnt=0
for /r %%F in (ratings.zil) do if "%%~dpF" neq "%target%\" (
if exist "%%F" (
if exist "%target%\%%~nxF" (
set /a cnt+=1
set "full=%%F"
set "name=%%~nF"
set "ext=%%~xF"
setlocal enableDelayedExpansion
copy "!full!" "!target!\!name!(!cnt!)!ext!" >nul
endlocal
) else copy "%%F" "%target%" >nul
)
)
I'm writing batch script which I'll use to copy files from location A to location B with rename of a source file from location A if the same file exists already in location B.
Currently Im using snippet from another topic here on stack but it doesnt work on files from subfolders, could anyone help me with code below so it work on all files and subdirectiories from both locations? Many thanks!
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET sourcedir="D:\TEST\FROM"
SET destdir="D:\TEST\TO"
SET /a count=0
for %%c in (%sourcedir%\*.*) do (
CALL :select
ECHO copy "%%c" "%destdir%\%%~nc_!count!%%~xc" /s
)
GOTO :EOF
:select
SET /a count+=1
IF EXIST "%destdir%\%%c" GOTO select
GOTO :eof
Replace your for loop with the following for loop:
for /R "%sourcedir%" %%c in (*.*) do (what you like)
Also, why do you want the following piece of code?
copy "%%c" "%destdir%\%%~nc_!count!%%~xc" /s
Just copy "%%c" %destdir%
More generally you can write:
#ECHO OFF
SET sourcedir="D:\TEST\FROM"
SET destdir="D:\TEST\TO"
:: SET /a count=0
for /R "%sourcedir%" %%c in (*.*) do (
:: SET /a count+=1
IF NOT EXIST "%destdir%\%%c" (
echo copy "%%c" %destdir%
)
)
Hope you are fine with this, possible dublicate of Windows batch file with loop through subfolders
Sharing with what I managed to get so far, works for what I needed, however still not doing well for subfolders:
#ECHO OFF
SET "sourcedir= "
SET "destdir= "
SET "HH=%TIME:~0,2%"
SET "MM=%TIME:~3,2%"
SET "SS=%TIME:~6,2%"
SET "_Time=%HH%%MM%%SS%"
FOR /R "%sourcedir%" %%G IN (*.*) DO (
IF EXIST "%destdir%\%%~nG%%~xG" (
COPY /V /Z "%%G" "%destdir%\%%~nG_duplicate_%_Time%%%~xG"
) ELSE (
COPY /V /Z "%%G" "%destdir%\%%~nG%%~xG")
)
The task is to Zip IIS Log Files(text files) and copy to another folder based on yesterday's date. And this batch script has to be Scheduled everyday.
I am very new to batch scripting. Any help is appreciated..!! Thanks.
I have this code which is copying the latest 3 files. But, I want to copy files only created on yesterday's date. And my file naming format is a_bc130510(a_bcYYMMDD).
enter code here
#ECHO OFF
SET srcdir=D:\IIS LOGS
SET tgtdir=D:\FileCopy
SET /A topcnt=3
SET /A cnt=0
FOR /F "tokens=*" %%F IN ('DIR /A-D /OD /TW /B "%srcdir%"') DO (
SET /A cnt+=1
SETLOCAL EnableDelayedExpansion
IF !cnt! GTR !topcnt! (ENDLOCAL & GOTO :EOF)
ENDLOCAL
COPY "%srcdir%\%%F" "%tgtdir%"
)
This is modified to copy the newest file from yesterday, as you asked.
This assumes your log filenames are abcYYMMDD.log
Change the term "%srcdir%\*%day%.log" if you need something else.
#echo off
call :getdate today -1
SET "srcdir=D:\IIS LOGS"
SET "tgtdir=D:\FileCopy"
FOR /F "delims=" %%F IN ('DIR /A-D /O-D /TW /B "%srcdir%\*%day%.log"') DO (
COPY "%srcdir%\%%F" "%tgtdir%"
goto :done
)
:done
rem extra code after the copy goes here
goto :EOF
:getdate
set date1=%1
set qty=%2
set separator=%~3
if /i "%date1%" EQU "TODAY" (set date1=now) else (set date1="%date1%")
echo >"%temp%\%~n0.vbs" s=DateAdd("d",%qty%,%date1%)
echo>>"%temp%\%~n0.vbs" WScript.Echo year(s)^&_
echo>>"%temp%\%~n0.vbs" right(100+month(s),2)^&_
echo>>"%temp%\%~n0.vbs" right(100+day(s),2)
for /f %%a in ('cscript //nologo "%temp%\%~n0.vbs"') do set result=%%a
del "%temp%\%~n0.vbs"
endlocal& set "YY=%result:~2,4%"&set "MM=%result:~4,2%"&set "DD=%result:~6,2%"
set "day=%YY%%separator%%MM%%separator%%DD%"
goto :EOF
I would like to call for help on my attempt to create a script which will automatically check last modified file and transfer it to destination.
What I have is this:
#Echo Off
Set _Delay=1
for /f "tokens=1,2,3 delims==" %%a in (config.ini) do (
if %%a==source set _Monitor=%%b
if %%a==destination set _Dest=%%b
if %%a==timer set _Timer=%%b
)
Set _Base=%temp%\BaselineState.dir
Set _Chck=%temp%\ChkState.dir
Set _OS=6
Ver|Findstr /I /C:"Version 5">Nul
If %Errorlevel%==0 Set _OS=5 & Set /A _Delay=_Delay*1000
Goto :_Xfer
:_StartMon
#echo off
SET R1=Start /w Sync1.vbs
Call :_SetBaseline "%_Base%" "%_Monitor%"
:_MonLoop
If %_OS%==5 (Ping 1.0.0.0 -n 1 -w %_Delay%>Nul) Else Timeout %_Delay%>Nul
Call :_SetBaseline "%_Chck%" "%_Monitor%"
FC /A /L "%_Base%" "%_Chck%">Nul
If %ErrorLevel%==0 Goto _MonLoop
::
for /l %%a in (%_Timer%,-1,0) do (
#Echo::::::::::::::::::::::::::::::::::::::::::::::
#Echo:: SEC Auto Transfer ::
#Echo:: Aizal 16 June 2012 ::
#Echo::::::::::::::::::::::::::::::::::::::::::::::
#Echo This script will scan SEC Data Folder for
#Echo new files every 30 minutes and will copy
#Echo it to the Server. Make sure you set correct
#Echo folder before using this script.
ECHO.
ECHO Currently recording:
FOR /F %%a in ('xcopy "%_Monitor%\*.SEC" "%_Dest%" /L /Y') DO (
IF NOT EXIST "%_Dest%.\%%~nxa" ECHO %%~nxa
)
ECHO Refreshing...
ECHO Please wait %%a seconds...
%R1%
cls
)
::
:_Xfer
FOR /F %%a in ('xcopy "%_Monitor%\*.SEC" "%_Dest%" /L /Y') DO (
IF NOT EXIST "%_Dest%.\%%~nxa" xcopy "%%a" "%_Dest%" /Y
)
::
Echo.Change Detected
ECHO.
Goto :_StartMon
:::::::::::::::::::::::::::::::::::::::::::::::::::
:: Subroutine
:::::::::::::::::::::::::::::::::::::::::::::::::::
:_SetBaseline
If Exist "%temp%\tempfmstate.dir" Del "%temp%\tempfmstate.dir"
For /F "Tokens=* Delims=" %%I In ('Dir /S "%~2"') Do (
Set _Last=%%I
>>"%temp%\tempfmstate.dir" Echo.%%I
)
>"%~1" Findstr /V /C:"%_Last%" "%temp%\tempfmstate.dir"
Goto :EOF
Now, if you noticed the script will compare the content of source folder with the content of the destination folder and will copy the files from source if there is not already file in destination. I would like to know if someone can help me figuring out how to make the script to check the last modified file in source folder and ONLY copy it to the destination AND if the said file is currently in use/being write to then script will wait until it finished before trying to copy it again.
Also, right now I have to edit source.ini file to specify which folder I want to monitor and each time I have to change the subfolder path to watch for changes, is there a way to watch parent folder for any new files and take that file to the destination?
I found this script on the net but hoping to check the file not based on day but instead of time.
::Copy Files Made Or Modified Today
#echo off
setlocal
set source= <source directory>
set dest= <destination directory>
pushd "%source%"
set t=%date:~4%
::for /f %%a in ('dir /b /a-d /o-d') do call :PROCESS "%%a"
goto :eof
popd
:PROCESS
for /f %%j in ('echo %~t1') do set d=%%j
if "%d%"=="%t%" copy %1 "%dest%"
goto :eof
Hope to find the solution from here.
Many thanks
With this you'll get the last modified file:
for /f %%A in ('dir /b /tw /o-d not-mandatory-file-mask') do (
set last_file=%%A
goto :endloop
)
:endloop
With this you'll copy the file if it is possible. If not it will try again and again:
:tryagain
set /a errorlevel=0
copy some_dir\%last_file% %destination%
if %errorlevel% NEQ 0 (
sleep 10
goto :tryagain
) else (
goto :end
)
:end