I have a frequent task of batch renaming images in a folder such that name consists of at least two digits, e.g. 01.jpg, 02.jpg, 03.jpg ... 140.jpg.
I want to achieve it using a batch file.
I have found some code but it is renaming only first 8 images of it.
#echo off
set i=1
for %%f in (*.jpg) do call :renameit "%%f"
goto done
:renameit
IF 1%i% LSS 1000 SET i=0%i%
ren %1 %i%.jpg
set /A i+=1
:done
This task could be done with a single command line in the batch file if there are definitely never 1.jpg and 01.jpg in the directory and there are never a.jpg, b.jpg, etc. in the directory with the *.jpg files.
#for %%I in (?.jpg) do #ren %%I 0%%I
To make the batch file more useful like adding it to Send To folder and using it via context menu (right click) on 1 or more selected directories containing the JPEG image files, it can be extended to support optionally one or more folder paths as parameter.
#echo off
set "Folder=%CD%"
:NextFolder
if not "%~1" == "" set "Folder=%~f1"
if "%Folder:~-1%" == "\" set "Folder=%Folder:~0,-1%"
for %%I in ("%Folder%\?.jpg") do ren "%%~fI" "0%%~nxI"
shift
if not "%~1" == "" goto NextFolder
set "Folder="
This batch files renames *.jpg files with a single character as file name by default only in current directory. But if the batch file is called with 1 or more folder paths (not validated), the batch file renames ?.jpg files in all the specified folders.
The folder paths passed to the batch file can be relative or absolute paths with or without backslash at end.
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.
echo /?
for /?
goto /?
if /?
ren /?
set /?
shift /?
Please note: The batch file is not 100% fail safe as it does not validate the folder paths or the found *.jpg files with just a single character as file name nor does it check for a file already existing with the new file name. However, error messages are printed if an error occurs like a file with new name already exists.
#echo off
set i=1
for %%f in (*.jpg) do call :renameit "%%f"
goto :eof
:renameit
if 1%i% lss 100 (ECHO ren %1 0%i%.jpg) else (ECHO ren %1 %i%.jpg)
set /A i+=1
goto :eof
did the rename directly, without a temporary variable. Remove the ECHOs, if the output is ok.
This answer is a join of answers posted by stephan
#echo off
set i=1
for %%f in (*.jpg) do call :renameit "%%f"
goto done
:renameit
IF 1%i% LSS 100 (SET new=0%i%) else (SET new=%i%)
ren %1 %new%.jpg
set /A i+=1
:done
Related
Hello and firstly I would like to apologize for this post if it was already answered before. I spent the last 4 hours searching Stackoverflow and Google.
I have a gamesettings.ini file I would like to edit via batch file. I need to perform this over many PCs, so I would like to keep the other settings besides 2 lines in the file.
The two lines im trying to change are:
CustomVoiceChatInputDevice=Default Input
CustomVoiceChatOutputDevice=Default Output
I tried a few batch scripts I found on Stackoverflow, but they only work if I define the full line. Since every user has different options set, i need the script to just take the start of the line. Just "CustomVoiceChatInputDevice" for example.
Here's an example code I used, thanks to #jsanchez. This script doesn't work unless I type out the whole line:
Thank you for your time!!
#echo off
::Use the path from whence the script was executed as
::the Current Working Directory
set CWD=C:\
::***BEGIN MODIFY BLOCK***
::The variables below should be modified to the
::files to be changed and the strings to find/replace
::Include trailing backslash in _FilePath
set _FilePath=C:\Users\NEOSTORM\AppData\Local\RedDeadGame\Saved\Config\WindowsClient\
set _FileName=GameUserSettings.ini
::_WrkFile is the file on which the script will make
::modifications.
set _WrkFile=GameUserSettings.bak
set OldStr="CustomVoiceChatInputDevice"
set NewStr="CustomVoiceChatInputDevice=Line (Astro MixAmp Pro Game)"
::***END MODIFY BLOCK***
::Set a variable which is used by the
::search and replace section to let us
::know if the string to be modified was
::found or not.
set _Found=Not found
SETLOCAL
SETLOCAL ENABLEDELAYEDEXPANSION
if not exist "%_FilePath%%_FileName%" goto :NotFound
::If a backup file exists, delete it
if exist "%_FilePath%%_WrkFile%" (
echo Deleting "%_FilePath%%_WrkFile%"
del "%_FilePath%%_WrkFile%" >nul 2>&1
)
echo.
echo Backing up "%_FilePath%%_FileName%"...
copy "%_FilePath%%_FileName%" "%_FilePath%%_WrkFile%" /v
::Delete the original file. No worries, we got a backup.
if exist "%_FilePath%%_FileName%" del "%_FilePath%%_FileName%"
echo.
echo Searching for %OldStr% string...
echo.
for /f "usebackq tokens=*" %%a in ("%_FilePath%%_WrkFile%") do (
set _LineChk=%%a
if "!_LineChk!"==%OldStr% (
SET _Found=Found
SET NewStr=!NewStr:^"=!
echo !NewStr!
) else (echo %%a)
)>>"%_FilePath%%_FileName%" 2>&1
::If we didn't find the string, rename the backup file to the original file name
::Otherwise, delete the _WorkFile as we re-created the original file when the
::string was found and replaced.
if /i "!_Found!"=="Not found" (echo !_Found! && del "%_FilePath%%_FileName%" && ren "%_FilePath%%_WrkFile%" %_FileName%) else (echo !_Found! && del "%_FilePath%%_WrkFile%")
goto :exit
:NotFound
echo.
echo File "%_FilePath%%_FileName%" missing.
echo Cannot continue...
echo.
:: Pause script for approx. 10 seconds...
PING 127.0.0.1 -n 11 > NUL 2>&1
goto :Exit
:Exit
exit /b
Each setting within your .ini file identifies the name of the setting. So the order of the lines should not may not matter.
If the line order is meaningless, then all you need do is use FINDSTR /V to remove the old values, and then simply append the new values. In the script below I modify both values at the same time.
#echo off
setlocal enableDelayedExpansion
set "iniLoc=C:\Users\NEOSTORM\AppData\Local\RedDeadGame\Saved\Config\WindowsClient"
set "iniFile=%iniLoc%\GameUserSettings.ini"
set "iniBackup=%iniLoc%\GameUserSettings.bak"
set "CustomVoiceChatInputDevice=Line (Astro MixAmp Pro Game)"
set "CustomVoiceChatOutputDevice=Some new value"
>"%iniFile%.new" (
findstr /vb "CustomVoiceChatInputDevice= CustomVoiceChatOutputDevice=" "%iniFile%"
echo CustomVoiceChatInputDevice=!CustomVoiceChatInputDevice!
echo CustomVoiceChatOutputDevice=!CustomVoiceChatOutputDevice!
)
copy "%iniFile%" "%iniBackup%"
ren "%iniFile%.new" *.
It would be slightly faster to create the backup file via rename instead of copy, but then there would be a brief moment where the ini file does not exist.
Windows command processor is not designed for editing text files, it is designed for running commands and applications.
But this text file editing/replacing task can be nevertheless done with cmd.exe (very slow):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "FileName=%LOCALAPPDATA%\RedDeadGame\Saved\Config\WindowsClient\GameUserSettings.ini"
set "TempFile=%TEMP%\%~n0.tmp"
if not exist "%FileName%" goto EndBatch
del "%TempFile%" 2>nul
for /F delims^=^ eol^= %%A in ('%SystemRoot%\System32\findstr.exe /N "^" "%FileName%"') do (
set "Line=%%A"
setlocal EnableDelayedExpansion
if not "!Line:CustomVoiceChatInputDevice=!" == "!Line!" (
echo CustomVoiceChatInputDevice=Line (Astro MixAmp Pro Game^)
) else if not "!Line:CustomVoiceChatOutputDevice=!" == "!Line!" (
echo CustomVoiceChatOutputDevice=Line (Astro MixAmp Pro Game^)
) else echo(!Line:*:=!
endlocal
) >>"%TempFile%"
rem Is the temporary file not binary equal the existing INI file, then move
rem the temporary file over existing INI file and delete the temporary file
rem if that fails like on INI file currently opened by an application with
rem no shared write access. Delete the temporary file if it is binary equal
rem the existing INI file because of nothing really changed.
%SystemRoot%\System32\fc.exe /B "%TempFile%" "%FileName%" >nul
if errorlevel 1 (
move /Y "%TempFile%" "%FileName%"
if errorlevel 1 del "%TempFile%"
) else del "%TempFile%"
:EndBatch
endlocal
See the answer on How to read and print contents of text file line by line? for an explanation of the FOR loop.
Please note the caret character ^ left to ) in the two lines to output. A closing parenthesis outside a double quoted argument string must be escaped here with ^ as otherwise ) would be interpreted by Windows command processor as end of command block and not as literal character to output by command ECHO. Other characters with special meaning for cmd.exe on parsing a command line or an entire command block like &|<> must be also escaped with ^ on ECHO command lines.
Please take also a look on Wikipedia article about Windows Environment Variables. It is highly recommended to use the right predefined environment variables for folder paths like local application data folder.
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 /? ... explains %~n0 ... batch file name without path and file extension.
del /?
echo /?
endlocal /?
fc /?
findstr /?
for /?
if /?
move /?
rem /?
set /?
setlocal /?
I already have a batch file that I can drop in any SHOW_NAME directory and it will move files from a sub-folder to its SEASON parent directory. For example:
F:\TV_SHOWS\SHOW_NAME\SEASON1\TITLE_EP1\title_episode1.mkv
F:\TV_SHOWS\SHOW_NAME\SEASON1\TITLE_EP2\title_episode2.mkv
F:\TV_SHOWS\SHOW_NAME\SEASON1\TITLE_EP3\title_episode3.mkv
F:\TV_SHOWS\SHOW_NAME\SEASON1\title_episode3.mkv
When it moves all files to the parent folder (SEASON1) the "title_episode3.mkv" is a duplicate and overwrites the original. How can I automatically rename by appending a number "title_episode3 (1).mkv"?
Here is the code that I use in a batch file:
#echo off
for /d /r %%f in (*) do (
for /d %%g in ("%%f\*") do (
for %%h in ("%%~g\*.mkv") do move "%%~h" "%%~f" >nul 2>&1
)
)
Thanks!
This commented batch file can be used for this task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Search for any file two directory levels below specified directory
rem and pass to subroutine MoveFile the name of the file with full path.
for /D %%A in ("F:\TV_SHOWS\SHOW_NAME\*") do (
for /D %%B in ("%%A\*") do (
for /F "delims=" %%I in ('dir "%%B\*" /A-D /B /S 2^>nul') do call :MoveFile "%%I"
)
)
endlocal
goto :EOF
:MoveFile
set "FilePath=%~dp1"
set "FileNameOnly=%~n1"
set "FileNameFull=%~1"
set "FileName+Ext=%~nx1"
set "FileExtension=%~x1"
rem For files staring with a dot and not containing one more dot.
if "%FileNameOnly%" == "" set "FileNameOnly=%~x1" & set "FileExtension="
rem Get path to parent folder ending with a backslash.
for /F "delims=" %%J in ("%FilePath:~0,-1%") do set "FileParent=%%~dpJ"
rem Uncomment the line below to see the values of the six File* variables.
rem set File & echo/
rem Does a file with current file name not exist in parent folder?
if not exist "%FileParent%%FileName+Ext%" (
rem Move the file to parent folder and if this was successful
rem delete the folder of the moved file if being empty now.
move "%FileNameFull%" "%FileParent%%FileName+Ext%" >nul
if not errorlevel 1 rd "%FilePath%" 2>nul
goto :EOF
)
set "FileNumber=1"
:NextFile
if exist "%FileParent%%FileNameOnly% (%FileNumber%)%FileExtension%" set /A "FileNumber+=1" & goto NextFile
move "%FileNameFull%" "%FileParent%%FileNameOnly% (%FileNumber%)%FileExtension%" >nul
if not errorlevel 1 rd "%FilePath%" 2>nul
goto :EOF
Running the batch file a second time on same directory with no new subdirectory and no new file does not change anything.
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 /?
echo /?
endlocal /?
for /?
goto /?
if /?
move /?
rd /?
rem /?
set /?
setlocal /?
See also:
the Microsoft article about Using Command Redirection Operators;
Single line with multiple commands using Windows batch file;
Where does GOTO :EOF return to?
I have a batch script already working for some months. The purpose of the script is to create a folder based on the file name and rename the folder accordingly for a certain purpose. However, it stops moving the files to the created folder in the loop. I tested it on other machine and it was working fine, but on a particular machine; it is just not working.
What can I do to make the loop effective and why did the batch stop working (moving files to folder) after working for many months now?
setlocal EnableDelayedExpansion
for /F %%a in ('dir "C:\Program Files\WinSCP\Unconverted" /a-d /b') do (
if not "%%~dpnxa"=="%~dpnx0" call :func "%%~a"
:func
set file=%~1
set dir=%file:~0,49%
mkdir "C:\Program Files\WinSCP\Unconverted\%dir%_fdc" 2>nul
rem ECHO "%file%"
rem ECHO "C:\Program Files\WinSCP\Unconverted\%dir%_fdc"
move /Y "C:\Program Files\WinSCP\Unconverted\%file%" "C:\Program Files\WinSCP\Unconverted\%dir%_fdc"
)
start "" "C:\Program Files\WinSCP\hide_conversion_window.exe"
I rewrote and commented the batch file as it contains several issues whereby most were not problematic as long as this batch file is stored in %ProgramFiles%\WinSCP\Unconverted and this directory is also the current directory on execution of the batch file as on double clicking the batch file.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceFolder=%ProgramFiles%\WinSCP\Unconverted"
rem Process all files in source folder found by command DIR with ignoring
rem subfolders and listed in bare format which means only file names with
rem file extension but without file path. The batch file itself is skipped
rem if being also stored in the source folder specified above.
for /F "delims=" %%I in ('dir "%SourceFolder%\*" /A-D /B 2^>nul') do (
if /I not "%SourceFolder%\%%I"=="%~f0" call :MoveFile "%SourceFolder%\%%I"
)
rem Execute converter through AutoIt in a separate command process and
rem while conversion is running continue with batch processing which means
rem restoring previous environment and finally exiting batch file processing.
start "" "%ProgramFiles%\WinSCP\hide_conversion_window.exe"
endlocal
goto :EOF
rem MoveFile is a subroutine which expects to be called with one argument
rem being the name of the file to move with full file name which means
rem with file path, file name and file extension.
rem The first 49 characters of the file name define the name for target
rem folder on which "_fdc" must be appended for completion. This folder
rem is created without verification on success and then the file is
rem moved into this folder again without verification on success.
:MoveFile
set "FileName=%~nx1"
set "FolderName=%FileName:~0,49%_fdc"
mkdir "%~dp1\%FolderName%" 2>nul
move /Y "%~1" "%~dp1\%FolderName%\" >nul
goto :EOF
This batch file works for batch file being stored in a different folder than source folder or current directory is a different directory than the folder containing the batch file or a found file contains a space character or any other special character like &()[]{}^=;!'+,`~.
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 /?
echo /?
endlocal /?
for /?
goto /?
if /?
mkdir /?
move /?
set /?
setlocal /?
start /?
Read also the Microsoft article about Using Command Redirection Operators.
Thanks for the suggestion oldabi. Sometimes things do work and we are thinking is all perfect until it breaks down. Thanks for the suggestion. I just realised my mistake about missing bracket.
SETLOCAL ENABLEDELAYEDEXPANSION
for /F %%a in ('dir "C:\Program Files\WinSCP\Unconverted" /a-d /b') do (
if not "%%~dpnxa"=="%~dpnx0" call :func "%%~a" )
goto conversion
:conversion
rem ::execute converter through autoit
start "" "C:\Program Files\WinSCP\hide_conversion_window.exe"
:func
set file=%~1
set dir=%file:~0,49%
mkdir "C:\Program Files\WinSCP\Unconverted\%dir%_fdc" 2>nul
rem ECHO "%file%"
rem ECHO "C:\Program Files\WinSCP\Unconverted\%dir%_fdc"
MOVE /Y "C:\Program Files\WinSCP\Unconverted\%file%" "C:\Program Files\WinSCP\Unconverted\%dir%_fdc"
My photo import tool (Picasa) does a great job at importing photos and videos from my phone and camera. What I like is that it creates a subfolder under the Pictures directory based on the Photo Taken Date of each photo/video. So you end up with this structure:
C:\Pictures\2017-02-01\DSC_0001.jpg
C:\Pictures\2017-02-01\DSC_0002.jpg
C:\Pictures\2017-02-01\DSC_0003.mp4 <--- problem
The only problem is that it puts videos in this same structure under Pictures.
As such, I'd like to right a batch script to find and move all video files (.mp4, .avi, .mov) from the C:\Pictures directory to the C:\Videos directory, but also with the date subfolder....
i.e.
Move C:\Pictures\2017-02-01\DSC_0003.mp4 to C:\Videos\2017-02-01\DSC_0003.mp4
Note that the date subfolder may or may not exist under C:\Videos.
Also since these are large video files, and there are a lot of them, I'd prefer a process that actually does a move and not a copy then delete, for the sake of speed and disk space utilization as I am almost out of space (after re-organizing these files, I will be archiving off to a NAS).
Also prefer using RoboCopy, xcopy, or xxcopy as I have them and use them today on my machine. If massively easier using PowerShell scripting, I can learn that if it is easy to do.
Final Solution
I used Mofi's answer, but enhanced it just a bit to add a function to calculate the directory string length
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Define folder with the pictures which is never deleted.
set "PicturesFolder=D:\Users\Chad\PicturesTest"
rem get string length of source directory to later use in a substring type function
call :strlen PicturesFolderDirectoryLength PicturesFolder
echo PicturesFolderDirectoryLength = %PicturesFolderDirectoryLength%
rem Change the current directory to directory with the pictures.
cd /D "%PicturesFolder%"
rem Search recursive in this directory for video files with
rem file extension AVI, MOV, MP4 or MPG and move those files.
for /F "delims=" %%I in ('dir /A-D /B /S *.avi *.mov *.mp4 *.mpg 2^>nul') do call :MoveVideo "%%I"
rem Discard all environment variables defined in this batch code
rem and restore initial current directory before exiting batch file.
endlocal
goto :EOF
rem MoveVideo is a subroutine called with name of current
rem video file name with full path by the FOR loop above.
rem It first defines target path for video file depending on source path
rem by removing the backslash at end and concatenating C:\Videos with the
rem source path omitting the first 11 characters which is C:\Pictures.
rem Then the target directory structure is created with redirecting the
rem error message output by command MD to handle STDERR in case of the
rem target directory already exists to device NUL to suppress it.
rem Next the video file is moved from source to target folder with silently
rem overwriting an already existing file with same name in target folder
rem because of using option /Y. Remove this option if a video file should
rem be kept in pictures folder and an error message should be displayed in
rem case of a video file with same name already existing in target folder.
rem Last the source folder is removed if it is completely empty which means
rem it does not contain any file or subfolder. All parent folders up to the
rem pictures folder are also removed if each parent folder is also empty
rem after deletion of an empty folder.
rem The subroutine is exited with goto :EOF and execution of batch file
rem continues in main FOR loop above with next found video file.
:MoveVideo
set "SourcePath=%~dp1"
set "SourcePath=%SourcePath:~0,-1%"
ECHO SourcePath=%SourcePath%
CALL SET "SourceSubFolder=%%SourcePath:~%PicturesFolderDirectoryLength%%%"
ECHO SourceSubFolder=%SourceSubFolder%
set "TargetPath=D:\Users\Chad\VideosTest%SourceSubFolder%"
echo TargetPath=%TargetPath%
md "%TargetPath%" 2>nul
move /Y "%~1" "%TargetPath%\%~nx1" >nul
:DeleteSourceFolder
rd "%SourcePath%" 2>nul
if errorlevel 1 goto :EOF
for /F "delims=" %%D in ("%SourcePath%") do set "SourcePath=%%~dpD"
set "SourcePath=%SourcePath:~0,-1%"
if /I not "%SourcePath%" == "%PicturesFolder%" goto DeleteSourceFolder
goto :EOF
:strlen <resultVar> <stringVar>
(
setlocal EnableDelayedExpansion
set "s=!%~2!#"
set "len=0"
for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if "!s:~%%P,1!" NEQ "" (
set /a "len+=%%P"
set "s=!s:~%%P!"
)
)
)
(
endlocal
set "%~1=%len%"
exit /b
)
Here is a commented batch code for this file moving task with keeping directory structure.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Define folder with the pictures which is never deleted.
rem Note: ~11 in third line of subroutine MoveVideo must be
rem replaced by ~length of the folder path defined here.
set "PicturesFolder=C:\Pictures"
rem Change the current directory to directory with the pictures.
cd /D "%PicturesFolder%"
rem Search recursive in this directory for video files with
rem file extension AVI, MOV, MP4 or MPG and move those files.
for /F "delims=" %%I in ('dir /A-D /B /S *.avi *.mov *.mp4 *.mpg 2^>nul') do call :MoveVideo "%%I"
rem Discard all environment variables defined in this batch code
rem and restore initial current directory before exiting batch file.
endlocal
goto :EOF
rem MoveVideo is a subroutine called with name of current
rem video file name with full path by the FOR loop above.
rem It first defines target path for video file depending on source path
rem by removing the backslash at end and concatenating C:\Videos with the
rem source path omitting the first 11 characters which is C:\Pictures.
rem Then the target directory structure is created with redirecting the
rem error message output by command MD to handle STDERR in case of the
rem target directory already exists to device NUL to suppress it.
rem Next the video file is moved from source to target folder with silently
rem overwriting an already existing file with same name in target folder
rem because of using option /Y. Remove this option if a video file should
rem be kept in pictures folder and an error message should be displayed in
rem case of a video file with same name already existing in target folder.
rem Last the source folder is removed if it is completely empty which means
rem it does not contain any file or subfolder. All parent folders up to the
rem pictures folder are also removed if each parent folder is also empty
rem after deletion of an empty folder.
rem The subroutine is exited with goto :EOF and execution of batch file
rem continues in main FOR loop above with next found video file.
:MoveVideo
set "SourcePath=%~dp1"
set "SourcePath=%SourcePath:~0,-1%"
set "TargetPath=C:\Videos%SourcePath:~11%"
md "%TargetPath%" 2>nul
move /Y "%~1" "%TargetPath%\%~nx1" >nul
:DeleteSourceFolder
rd "%SourcePath%" 2>nul
if errorlevel 1 goto :EOF
for /F "delims=" %%D in ("%SourcePath%") do set "SourcePath=%%~dpD"
set "SourcePath=%SourcePath:~0,-1%"
if /I not "%SourcePath%" == "%PicturesFolder%" goto DeleteSourceFolder
goto :EOF
This batch file also removes all folders in C:\Pictures which become empty after moving the video files. But it does not remove folders which were already empty on starting the batch file.
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.
cd /?
echo /?
endlocal /?
for /?
goto /?
if /?
md /?
move /?
rd /?
rem /?
set /?
setlocal /?
Read also the Microsoft article about Using Command Redirection Operators for an explanation of >nul and 2>nul. In the main FOR loop the redirection operator > is escaped with caret character ^ to be interpreted as literal character on parsing FOR command line and later as redirection operator on execution of DIR command line by FOR.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
XCOPY /T "%sourcedir%" "%destdir%"
FOR %%x IN (mp4 mov) DO (
FOR /f "tokens=1*delims=>" %%a IN (
'XCOPY /Y /s /d /F /L "%sourcedir%\*.%%x" "%destdir%"'
) DO IF "%%b" neq "" (
SET "topart=%%b"
SET "frompart=%%a"
ECHO(MOVE /y "!frompart:~0,-2!" "!topart:~1!"
)
)
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
The required MOVE 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. Append >nul to suppress report messages (eg. 1 file moved)
The first xcopy creates the required subtrees, the second uses the /L option to list rather than copy the files
The loop on %%x assigns %%x to the required extensions. The output from the inner xcopy will be of the form fullsourcefilename -> fulldestinationfilename so it needs to be parsed using > as a delimiter, from-filename to %%a, to-filename to %%b. If %%b is not set, then this is the final line of xcopy's report (n files copied) which needs to be ignored. The to and from filenames need to be trimmed of unwanted, but fortunately constant character strings.
What is interesting is that there appears to be no way using xcopy to suppress prompting in the case where the destination filename already exists.
I want to copy more than 1000 files from a source folder like
sourcefolder\prod_de_7290022.xlsx
sourcefolder\prod_de_1652899.xlsx
sourcefolder\prod_de_6272899.xlsx
sourcefolder\prod_de_6189020.xlsx
sourcefolder\prod_de_7290022.wav
sourcefolder\prod_de_1652899.wav
sourcefolder\prod_de_6272899.wav
sourcefolder\prod_de_6189020.wav
sourcefolder\prod_de_7290022_mark.xlsx
sourcefolder\prod_de_1652899_mark.xlsx
sourcefolder\prod_de_6272899_mark.xlsx
sourcefolder\prod_de_6189020_mark.xlsx
to the right destination folder. The folder names are - based on another routine - long and only the first 15 characters are identical with the first 15 characters of each file name, like:
destination\prod_de_1652899_tool_big\
destination\prod_de_6272899_bike_red\
destination\prod_de_6189020_bike-green\
destination\prod_de_7290022_camera_good\
I am looking for a routine to copy the files into the folder, like sourcefolder\prod_de_1652899.xlsx into destination\prod_de_1652899_tool_big\.
Is here anyone with a good idea for a batch/script?
I suggest to use this commented batch code for this task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceFolder=sourcefolder"
set "TargetFolder=destination"
rem Call subroutine CopyFile for each non hidden and
rem non system file found in specified source folder
rem and then exit processing of this batch file.
for %%I in ("%SourceFolder%\*") do call :CopyFile "%%~fI"
endlocal
goto :EOF
rem This is a subroutine called for each file in source folder.
rem It takes the first 15 characters from each file name passed
rem to this subroutine via first parameter and search for a
rem folder in target folder starting with same 15 characters.
rem If such a folder is found, the file is copied to this folder
rem and the subroutine is exited.
rem Otherwise a new folder is created for the file and if
rem this is indeed successful, the file is copied into the
rem newly created folder with an appropriate message.
:CopyFile
set "FileName=%~n1"
set "DirectoryName=%FileName:~0,15%"
for /D %%D in ("%TargetFolder%\%DirectoryName%*") do (
copy /B /Y %1 /B "%%~D\" >nul
goto :EOF
)
set "NewFolder=%TargetFolder%\%DirectoryName%_new"
md "%NewFolder%"
if exist "%NewFolder%\" (
echo Created new folder: %NewFolder%
copy /B /Y %1 /B "%NewFolder%\" >nul
goto :EOF
)
echo Failed to create folder: %NewFolder%
echo Could not copy file: %1
goto :EOF
To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.
call /?
copy /?
echo /?
endlocal /?
for /?
goto /?
if /?
md /?
rem /?
set /?
setlocal /?