Batch loop error - only 1 file is copied - windows

I'm trying to run a bat file that:
creates a folder
searches for all files with .log extension
Copies and rename the files to MyFile_customString.log to another folder
So far I did this:
#echo off
set host_name=%1
set origin_path=%2
set destiny_path=%3
set destiny_host_path=%destiny_path%\%host_name%\
mkdir .\%destiny_host_path%
FOR %%G IN (%origin_path%/*.log) DO (
SET _fileName=%%G
SET _custom=%_fileName:.log=_%%host_name%.log%
xcopy /Y /F %origin_path%\%_fileName% %destiny_host_path%\%_custom%
)
And having MyTest.log and MyTest2.log files in origin_path only MyTest2.log file is copied to destiny_host_path
What am I missing?

You need SetLocal EnableDelayedExpansion at top of batch file after #echo
In your code:
FOR %%G IN (%origin_path%/*.log) DO (
SET _fileName=%%G
SET _custom=%_fileName:.log=_%%host_name%.log%
xcopy /Y /F %origin_path%\%_fileName% %destiny_host_path%\%_custom%
)
should be:
FOR %%G IN (%origin_path%/*.log) DO (
SET "_fileName=%%G"
FOR %%H in (!host_name!) Do (
SET "_custom=!_fileName:.log=_%%H.log!"
)
xcopy /Y /F !origin_path!\!_fileName! !destiny_host_path!\!_custom!
)

FOR %%G IN (%origin_path%\*.log) DO (
xcopy /Y /F "%origin_path%\%%G" "%destiny_host_path%\%%~nG_%host_name%.log"
)
(untested)
No need for delayedexpansion in this case.
See for /? |more from the prompt for information on the use of ~-modifiers to extract parts of filenames.
In your original, your %s were unbalanced (assuming that % had been correct in that context) in the set _custom line.
Tip: replace xcopy with echo xcopy temporarily to show rather than execute the command - easier to debug in case of an error...

Related

Copy files based on the extension length of the file?

i'm looking for a way on Windows to find all files with a specific file extension length and copy them to another location while preserving the folder structure.
For example lets say that I want to copy all files on my D: drive, with a file extension length of excatly six (*.******) and copy them to another location while also keeping the folder structure.
Is this possible in CMD?.
C:\Users\PeterR>copy C:\Users\PeterR\Documents\cmd\???.txt C:\Users\PeterR\Documents\cmd1\
--use ? to specify the lentgh. for six characters it's ??????.extension
What about the following code snippet:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_SOURCE=D:\"
set "_DESTIN=E:\"
pushd "%_SOURCE%" || exit /B 1
for /F "delims=" %%F in ('
xcopy /L /E /I ".\*.*" "E:\" ^| find ".\"
') do (
for /R "D:\" %%F in ("*.*") do (
set "EXT=%%~xF"
setlocal EnableDelayedExpansion
if "!EXT:~6!"=="" if not "!EXT!"=="!EXT:~5!" (
endlocal
move /Y "%%~F" "%_DESTIN%\%%~F"
) else endlocal
)
popd
endlocal
exit /B

How to copy several specified files from a source folder and its subfolders to a destination folder?

I have source folder: c:\prefix\bin
I want to copy a set of specified files from source folder and its subfolders.
Lets say I want to copy:
bin
... gtsam.dll
... msvcr120.dll
... intel64\
... vc12\
... tbb.dll
To be more clearly for what I want to copy:
.\gtsam.dll .\msvcr120.dll .\intel64\vc12\tbb.dll
There are many files in the source directory and many subdirectories that I don't want to copy. And all the specified files I have to copy do not share a wild card. They are not all *.dll to copy to c:\dst
How I can do it with the most elegant way?
Using copy, or xcopy, or robocopy?
I suggest to create first a simple text file containing line by line the files to copy with relative path.
Example for FilesList.txt:
gtsam.dll
msvcr120.dll
intel64\vc12\tbb.dll
It is up to you in which directory to store this list file with the names of the files to copy.
The code below expects this file in directory C:\prefix\bin.
Then create a batch file with following code:
#echo off
pushd "C:\prefix\bin"
for /F "usebackq delims=" %%F in ("FilesList.txt") do (
%SystemRoot%\System32\xcopy.exe "%%~F" C:\dst\ /C /H /I /K /Q /R /Y >nul
)
popd
If target is specified with a backslash at end as done here and option /I is used, console application xcopy expects that C:\dst is a directory and even creates the entire directory structure to this directory automatically if not already existing.
Or you use this script with command copy and making sure the destination directory exists before copying the files.
#echo off
if not exist "C:\dst" (
md "C:\dst"
if errorlevel 1 (
echo.
echo Failed to create directory C:\dst
echo.
pause
goto :EOF
)
)
pushd "C:\prefix\bin"
for /F "usebackq delims=" %%F in ("FilesList.txt") do (
copy /B /Y "%%~F" C:\dst\ >nul
)
popd
Command md creates also entire directory tree on creating a directory with command extensions enabled as by default.
In both cases the directory C:\dst contains after batch file execution:
gtsam.dll
msvcr120.dll
tbb.dll
The main advantage of using a list file containing the names of the files to copy with relative path is easy updating in future without the need to change the batch code.
But let's say the files should be copied with duplicating the directory structure from source to destination directory resulting in directory C:\dst containing after batch file execution:
gtsam.dll
msvcr120.dll
intel64
vc12
tbb.dll
In this case the batch code with xcopy could be:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
pushd "C:\prefix\bin"
if "%CD:~-1%" == "\" ( set "BasePath=%CD%" ) else ( set "BasePath=%CD%\" )
for /F "usebackq delims=" %%F in ("FilesList.txt") do (
set "SourcePath=%%~dpF"
set "RelativePath=!SourcePath:%BasePath%=!"
%SystemRoot%\System32\xcopy.exe "%%~F" "C:\dst\!RelativePath!" /C /H /I /K /Q /R /Y >nul
)
popd
endlocal
And the batch code using copy could be:
#echo off
if not exist "C:\dst" (
md "C:\dst"
if errorlevel 1 (
echo.
echo Failed to create directory C:\dst
echo.
pause
goto :EOF
)
)
setlocal EnableDelayedExpansion
pushd "C:\prefix\bin"
if "%CD:~-1%" == "\" ( set "BasePath=%CD%" ) else ( set "BasePath=%CD%\" )
for /F "usebackq delims=" %%F in ("FilesList.txt") do (
set "SourcePath=%%~dpF"
set "RelativePath=!SourcePath:%BasePath%=!"
md "C:\dst\!RelativePath!" 2>nul
copy /B /Y "%%~F" "C:\dst\!RelativePath!" >nul
)
popd
endlocal
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.
copy /?
echo /?
endlocal /?
if /?
for /?
goto /?
md /?
pause /?
popd /?
pushd /?
set /?
setlocal /?
xcopy /?
Not tested:
#echo off
set "basedir=c:\prefix\bin"
set "destination=c:\destination"
for /r "%basedir%" %%# in (*gtsam.dll *msvcr120.dll *tbb.dll) do (
copy "%%~f#" "%destination%"
)

How to batch copy files based on a list (txt) of PREFIXES

My filenames contain somewhat standardized prefixes. Generally, the format is yyyy-99999-xx.
Filename examples:
2015-12345-NY-0 Coney Island
2015-12345-NY-1 Coney Island
2015-54321-NY Coney Island
As you can see, there can be multiple files containing identical characters 1 thru n. I would like to copy files from a folder by searching for prefixes contained in a .txt file list.
Basically, I would like to "refine/expand" the process shown in Batch: Copy a list (txt) of files so that file-list.txt - I've changed to Prefix-List.txt - contains only the filename "prefixes" of the files to copy. I had to change the xcopy switch to /K in order to copy any files.
Additionally, I would like to redirect errors to Errors.txt
"Nice to have" would be including subfolders in the search.
Using my filename examples above:
2015 would copy 3 files.
2015-12345-NY would copy 2 files.
2015-12345-NY-1 would copy 1 file.
Here's my .bat file
set src_folder=d:\JAR\source
set dst_folder=d:\JAR\destination
for /f "tokens=*" %%i in (File-list.txt) DO (
xcopy /K "%src_folder%\%%i" "%dst_folder%"
)
Mofi's solution is exactly what I asked for. Now I'd like to expand a little by changing the destination directory name & adding a date-time prefix.
I have 2 questions
1. How to get Mon=08 (instead of Aug)?
2. What is syntax for MKDIR using a variable?
Here's the coding I'm using (modified from Windows batch: formatted date into variable ).
#echo off
setlocal
for /f "skip=8 tokens=2,3,4,5,6,7,8 delims=: " %%D in ('robocopy /l * \ \ /ns /nc /ndl /nfl /np /njh /XF * /XD *') do (
set "dow=%%D"
set "month=%%E"
set "day=%%F"
set "HH=%%G"
set "MM=%%H"
set "SS=%%I"
set "year=%%J"
SET "DESTINATION=%%J%%E%%F%%G%%H%%I-EXTRACTION"
)
echo Day of the week: %dow%
echo Day of the month : %day%
echo Month : %month%
echo hour : %HH%
echo minutes : %MM%
echo seconds : %SS%
echo year : %year%
echo DESTINATION : %DESTINATION%
endlocal
MKDIR {"%DESTINATION%"}
This doesn't have a lot of testing, but it might point in the right direction.
set src_folder=d:\JAR\source
set dst_folder=d:\JAR\destination
for /f "tokens=*" %%i in (File-list.txt) DO (
for /f "usebackq tokens=*" %%k in (`dir /s /b "%src_folder%\%%i*") DO
xcopy /K "%%k" "%dst_folder%"
)
)
Here is my suggestion for this little batch file with comments:
#echo off
rem Define source and destination directory.
set "src_folder=d:\JAR\source"
set "dst_folder=d:\JAR\destination"
rem Delete error log file from a previous run.
del Errors.txt 2>nul
rem Copy all files in all subdirectories matching
rem any prefix string in prefix list text file.
for /F "delims=" %%i in (Prefix-List.txt) do (
xcopy "%src_folder%\%%i*" "%dst_folder%" /C /H /I /K /Q /R /S /Y >nul 2>>Errors.txt
)
rem Delete Errors.txt if it is empty because of no error.
for %%F in (Errors.txt) do if %%~zF == 0 del Errors.txt
But I doubt you are really happy with error information as xcopy error messages are really not useful without printing copied files to console and redirecting them all into the text file, too.
For details on the used command, open a command prompt window, run there the following commands and read all output help pages.
del /?
for /?
if /?
set /?
xcopy /?
Extensions:
Make the source folder a variable passed via first parameter to batch file on execution.
Display an error message if batch file is executed without a parameter.
Display an error message if specified source folder does not exist.
Prefix yyyy-mm-dd_ for destination directory independent on local date format.
This modified version of above batch file includes the two extensions:
#echo off
rem Check first parameter of batch file.
if "%~1" == "" goto NoSourceFolder
if not exist "%~1" goto SourceNotExist
if not exist Prefix-List.txt goto NoPrefixList
setlocal
rem Define source directory based on parameter.
set "src_folder=%~1"
rem Get local date and time in a language independent format.
for /F "tokens=2 delims==." %%T in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "LocalDate=%%T"
rem Define local date in format yyyy-mm-dd.
set "LocalDate=%LocalDate:~0,4%-%LocalDate:~4,2%-%LocalDate:~6,2%"
rem Define destination directory with date prefix.
set "dst_folder=d:\JAR\%LocalDate%_destination"
rem Delete error log file from a previous run.
del Errors.txt 2>nul
rem Copy all files in all subdirectories matching
rem any prefix string in prefix list text file.
for /F "delims=" %%i in (Prefix-List.txt) do (
xcopy "%src_folder%\%%i*" "%dst_folder%" /C /H /I /K /Q /R /S /Y >nul 2>>Errors.txt
)
rem Delete Errors.txt if it is empty because of no error.
for %%F in (Errors.txt) do if %%~zF == 0 del Errors.txt
endlocal
goto :EOF
:NoSourceFolder
echo %~nx0: Missing source folder name as first parameter.
goto HaltOnError
:SourceNotExist
echo %~nx0: There is no folder "%~1".
goto HaltOnError
:NoPrefixList
echo %~nx0: There is no file "%CD%\Prefix-List.txt".
:HaltOnError
echo.
pause
Thanks goes to Jay for answer on How to get current datetime on Windows command line, in a suitable format for using in a filename?
For details on %~1 and %~nx0 run in a command prompt window call /? and read all the output help pages, and read also What does %~dp0 mean, and how does it work?.

Windows cmd sort files by file type and store them in folder

I would like to have a batch file wich will sort files by file type and sorts them into folder.
For example I will run this batch file in some folder and .PDF files will be saved in "PDF" folder, same to do with other file types. Is possible to do that in command line?
Thank you.
Please put the code below in a .bat file and save it to your folder with files and run it.
#echo off
rem For each file in your folder
for %%a in (".\*") do (
rem check if the file has an extension and if it is not our script
if "%%~xa" NEQ "" if "%%~dpnxa" NEQ "%~dpnx0" (
rem check if extension forlder exists, if not it is created
if not exist "%%~xa" mkdir "%%~xa"
rem Copy (or change to move) the file to directory
copy "%%a" "%%~dpa%%~xa\"
)
)
Try this:
#echo off
setlocal enabledelayedexpansion
for %%a in (*.*) do (
set "fol=%%~xa" & set "fol=!fol:.=!"
if not exist !fol! md !fol!
for /f %%b in ('dir /on /b *.*') do (
if %%~xb EQU .!fol! move %%~nxb !fol!
)
)
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET destdir=c:\destdir
SET "extdone=:"
FOR /f "delims=" %%a IN ('dir /b /a-d') DO (
SET ext=%%~xa
IF DEFINED ext (
SET extdone|FIND /i ":%%~xa:" >NUL
IF ERRORLEVEL 1 (
SET extdone=:%%~xa: !extdone!
IF EXIST "%destdir%\!ext:~1!" (
ECHO MOVE "*%%~xa" "%destdir%\!ext:~1!"
) ELSE (ECHO no MOVE "%%~xa")
)
)
)
GOTO :EOF
This batch should do as you ask.
The required commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO MOVE to MOVE to actually move the files.
I've assumed that you only wish to move the files if destinationdirectory\extensionfound exists. If you want to create a directory for a new extension, simply add a line
md "%destdir%\!ext:~1!" 2>nul
after the SET extdone=:%%~xa: !extdone! line.

Make subfolder names from part of file name and copy files with Robocopy

Is it posible to copy and make directories automatically from file name substrings using Robocopy?
I mean i have files like these. LAJ00306130201004626.rc the first 8 chararacters are control number (LAJ00306=control number) this would be the name of the folder and the rest are the date and time (Date=130201) (time=004626).
LAJ00306130201004626.rc
LAJ00306130202004626.rc
LAJ00306130203004626.rc
LAJ00307130201004626.rc
LAJ00307130202004626.rc
and i would like to copy and create folders from the file name like under and copy the files mentioned before in the new folders.
LAJ00306
LAJ00307
I hope to be clear if necessary ask me for more information
try this, look at the output and remove the echos before MD and ROBOCOPY, if it looks good:
#ECHO OFF &SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcefolder=."
SET "targetfolder=X:\data"
CD /d "%sourcefolder%"
FOR %%a IN (*.rc) DO (
SET "fname=%%a"
SET "folder=!fname:~0,8!"
SET "$!folder!=1"
)
FOR /f "delims=$=" %%a IN ('set "$"') DO (
ECHO MD "%targetfolder%\%%a" 2>nul
ECHO ROBOCOPY "%sourcefolder%" "%targetfolder%\%%a" "%%a*.rc"
)
Set sourcefolder and targetfolder for your folder tree.
Try this:
#echo off
pushd "c:\source folder"
setlocal enabledelayedexpansion
for %%a in (*.rc) do (
set "name=%%a"
robocopy "%cd%" "%%a" "D:\target directory\!name:~0,8!"
)
popd
Answers to your questions are:
pushd "drive:\path" makes the location the current working directory.
popd restores the last working directory
setlocal enabledelayedexpansion allows you to change and use variables within a loop, using the !variable! syntax.
If your 2000 files are in a single folder then it should work - but test it on some sample files first so that you can see how it will work.
#ECHO OFF
SETLOCAL
SET "sourcedir=."
SET "destdir=c:\destdir"
FOR /f "tokens=1*delims=_" %%i IN (
'dir /b /a-d "%sourcedir%\*_*."'
) DO XCOPY /b "%sourcedir%\%%i_%%j" "%destdir%\%%i\"
GOTO :EOF
This should accomplish the task described. You'd need to set up the source and destination directories to suit, of course. Add >nul to the end of the XCOPY line to suppress 'copied' messages.

Resources