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.
Related
I would like to create a .bat files that asks for a file extension and a path, then scans the directory and subfolders where the .bat file itself in located looking the all the files with the extension provided and moves them to the specified path while creating a .lnk in the original location.
For example the .bat would behave like this:
Enter file extension: mkv
Enter new path: e:\movies
Then it scans folder and subfolders of where the .bat file is located and move all the .mkv files to the new path, while creating a .lnk in the original source folder for each file that has been moved.
I want to copy also the original source structure to the new one. For example if I have a .mkv file in d:\star trek\movie1\a.mkv I would like to have e:\movies\star trek\movie1\a.mkv and then d:\star trek\movie1\a.lnk. The .lnk should link to the moved file in folder on drive e:.
Any ideas would be highly appreciated.
As a first step, I would like to create a simple batch that asks the user for an extension and then just lists all the files with that extension.
I wrote:
#echo off
set /p type= File type?
dir *.type > list.txt
But that doesn't work. Any suggestions?
I found some code here How to copy a directory structure but only include certain files (using windows batch files) and I'm just learning it. I've wrote down this simple adaptation but I don't understand why the last echo doesn't output what I intend, e.g. the whole destination path and file name. I must be doing something stupid I know!
#echo off
cls
setlocal enabledelayedexpansion
set SOURCE_DIR=K:\source
set DEST_DIR=K:\dest
set FILENAMES_TO_COPY=*.txt
for /R "%SOURCE_DIR%" %%F IN (%FILENAMES_TO_COPY%) do (
if exist "%%F" (
echo source: %%F
set FILE_DIR=%%~dpF
set FILE_INTERMEDIATE_DIR=!FILE_DIR:%SOURCE_DIR%=!
set FILE_NAME_EXT=%%~nxF
set FILE_DIR
set FILE_INTERMEDIATE_DIR
set FILE_NAME_EXT
xcopy /S /I /Y /V "%%F" "%DEST_DIR%!FILE_INTERMEDIATE_DIR!"
echo destination "%DEST_DIR%!FILE_INTERMEDIATE_DIR%FILE_NAME_EXT!"
pause
)
)
For the batch file below download very small ZIP file Shortcut.zip from Optimum X Downloads - Freeware Utilities, extract the ZIP file to a temporary directory, read file ReadMe.txt of this freeware utility and move Shortcut.exe into same folder as the batch file.
Here is the commented batch code for this task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
if not exist "%~dp0Shortcut.exe" (
echo ERROR: Missing Shortcut.exe in "%~dp0".
goto EndBatch
)
:GetExtension
set "FileExt="
set /P "FileExt=Enter file extension: "
rem Has the user not entered any string?
if not defined FileExt goto GetExtension
rem Remove all double quotes.
set "FileExt=%FileExt:"=%"
rem Is there nothing left after removing double quotes?
if not defined FileExt goto GetExtension
rem Is the first character a dot, then remove it.
if "%FileExt:~0,1%" == "." set "FileExt=%FileExt:~1%"
rem Is there nothing left after removing the dot?
if not defined FileExt goto GetExtension
rem Does the entered file extension string contain a
rem character which is not allowed in a file extension?
set "TempVar="
for /F "eol=| delims=*./:<>?\|" %%I in ("%FileExt%") do set "TempVar=%%I"
if not "%TempVar%" == "%FileExt%" goto GetExtension
rem Don't allow moving *.lnk shortcut files.
if /I "%FileExt%" == "lnk" goto GetExtension
:GetSourcePath
set "SourcePath=%~dp0"
set /P "SourcePath=Enter source path: "
set "SourcePath=%SourcePath:"=%"
if not defined SourcePath goto GetSourcePath
rem Replace all forward slashes by backslashes.
set "SourcePath=%SourcePath:/=\%"
rem Remove a trailing backslash.
if "%SourcePath:~-1%" == "\" set "SourcePath=%SourcePath:~0,-1%"
rem Recreate the environment variable if the entered source directory path
rem was just a backslash to reference root directory of current drive.
if not defined SourcePath set "SourcePath=\"
rem Does the entered source path string contain a
rem character which is not allowed in a folder path?
set "TempVar="
for /F "eol=| delims=*<>?|" %%I in ("%SourcePath%") do set "TempVar=%%I"
if not "%TempVar%" == "%SourcePath%" goto GetSourcePath
rem Determine full qualified source folder path.
for %%I in ("%SourcePath%") do set "SourcePath=%%~fI"
rem Remove once again a trailing backslash which can occur
rem if the source folder is the root folder of a drive.
if "%SourcePath:~-1%" == "\" set "SourcePath=%SourcePath:~0,-1%"
rem The source directory must exist.
if not exist "%SourcePath%\" (
echo/
echo ERROR: Source directory "%SourcePath%" does not exist.
echo/
goto GetSourcePath
)
:GetTargetPath
set "TargetPath="
set /P "TargetPath=Enter target path: "
if not defined TargetPath goto GetTargetPath
set "TargetPath=%TargetPath:"=%"
if not defined TargetPath goto GetTargetPath
rem Replace all forward slashes by backslashes.
set "TargetPath=%TargetPath:/=\%"
rem Remove a trailing backslash.
if "%TargetPath:~-1%" == "\" set "TargetPath=%TargetPath:~0,-1%"
rem Recreate the environment variable if the entered target directory path
rem was just a backslash to reference root directory of current drive.
if not defined TargetPath set "TargetPath=\"
rem Does the entered target path string contain a
rem character which is not allowed in a folder path?
set "TempVar="
for /F "eol=| delims=*<>?|" %%I in ("%TargetPath%") do set "TempVar=%%I"
if not "%TempVar%" == "%TargetPath%" goto GetTargetPath
rem Determine full qualified target folder path.
for %%I in ("%TargetPath%") do set "TargetPath=%%~fI"
rem Remove once again a trailing backslash which can occur
rem if the target folder is the root folder of a drive.
if "%TargetPath:~-1%" == "\" set "TargetPath=%TargetPath:~0,-1%"
rem Is the target path identical to source folder path?
if /I "%SourcePath%" == "%TargetPath%" (
echo/
echo ERROR: Target path cannot be the source path.
echo/
goto GetTargetPath
)
rem Does the specified target folder exist?
if exist "%TargetPath%\" goto GetPathLength
rem Ask user if target folder should be created or not.
echo/
echo ERROR: Folder "%TargetPath%" does not exist.
echo/
%SystemRoot%\System32\choice.exe /C YN /N /M "Create path (Y/N)? "
echo/
if errorlevel 2 goto GetTargetPath
md "%TargetPath%" 2>nul
if exist "%TargetPath%\" goto GetPathLength
echo ERROR: Could not create "%TargetPath%".
echo/
goto GetTargetPath
rem Determine length of source path (path of batch file).
:GetPathLength
setlocal EnableDelayedExpansion
set "PathLength=0"
:GetLength
if not "!SourcePath:~%PathLength%!" == "" set /A "PathLength+=1" & goto GetLength
rem For the additional backslash after source folder path.
set /A PathLength+=1
endlocal & set "PathLength=%PathLength%"
rem Move the non-hidden files with matching file extension with exception
rem of the batch file and Shortcut.exe. Use FOR /F with a DIR command line
rem instead of FOR /R to get this code working also on FAT32 and ExFAT
rem drives and when target folder is a subfolder of the batch file.
set "FileCount=0"
for /F "eol=| delims=" %%I in ('dir "%SourcePath%\*.%FileExt%" /A-D-H /B /S 2^>nul') do if /I not "%%I" == "%~f0" if /I not "%%I" == "%~dp0Shortcut.exe" call :MoveFile "%%I"
set "PluralS=s"
if %FileCount% == 1 set "PluralS="
echo Moved %FileCount% file%PluralS%.
goto EndBatch
:MoveFile
rem Do not move a file on which there is already a shortcut file
rem with same file name in source directory because then it would
rem not be possible to create a shortcut file for the moved file.
if exist "%~dpn1.lnk" goto :EOF
rem Get entire path of source file and remove path of batch file.
set "SourceFilePath=%~dp1"
call set "RelativePath=%%SourceFilePath:~%PathLength%%%"
rem Create target file path for this file.
set "TargetFilePath=%TargetPath%\%RelativePath%"
echo TargetFilePath=%TargetFilePath%
rem Remove trailing backslash if there is one.
if "%TargetFilePath:~-1%" == "\" set "TargetFilePath=%TargetFilePath:~0,-1%"
rem Create the target folder independent on its existence
rem and verify if the target folder really exists finally.
md "%TargetFilePath%" 2>nul
if not exist "%TargetFilePath%\" (
echo ERROR: Could not create folder "%TargetFilePath%".
goto :EOF
)
rem Move the file to target folder and verify if that was really successful.
rem On error remove a just created target folder not containing a file.
move /Y %1 "%TargetFilePath%\" 2>nul
if errorlevel 1 (
rd "%TargetFilePath%" 2>nul
echo ERROR: Could not move file %1.
goto :EOF
)
rem Create the shortcut file in source directory of moved file.
"%~dp0Shortcut.exe" /F:"%~dpn1.lnk" /A:C /T:"%TargetFilePath%\%~nx1" /W:"%TargetFilePath%" /R:1 >nul
set /A FileCount+=1
goto :EOF
:EndBatch
endlocal
pause
The batch file contains lots of extra code to be fail safe as much as possible against wrong user input.
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 /?
choice /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
md /?
move /?
rd /?
rem /?
set /?
setlocal /?
See also:
Where does GOTO :EOF return to?
What does %~dp0 mean, and how does it work?
Microsoft article about Using command redirection operators
Single line with multiple commands using Windows batch file
How does the Windows Command Interpreter (CMD.EXE) parse scripts?
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?
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"
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
I would like to use a batch file to delete all blank lines in multiple files in the directory "Data". I don't want to rename the files.
I have seen this post, but it does not help: How to delete blank lines from multiple files in a directory for the following reasons:
* Files are renamed
* Files must be in same directory as the .bat file
If you could also explain the batch file commands, then that would be greatly appreciated.
Thanks.
I've decided to include all the explanations as comments. There are some ways of doing it without a rename/move operation, but are not as reliable as this. Anyway, at the end, files will have the same name but no empty lines.
#echo off
setlocal enableextensions disabledelayedexpansion
rem There are some problems with references to batch files
rem that are called with quotes. To avoid the problems, a
rem subroutine is used to retrieve the information of
rem current batch file
call :getBatchFileFullPath batch
rem From the full path of the batch file, retrieve the
rem folder where it is stored
for %%a in ("%batch%") do set "folder=%%~dpa"
rem We will use a temporary file to store the valid
rem lines while removing the empty ones.
set "tempFile=%folder%\~%random%%random%%random%"
rem For each file in the batch folder, if the file is
rem not the batch file itself
for %%a in ("%folder%\*") do if /i not "%%~fa"=="%batch%" (
rem Now %%a holds a reference to the file being processed
rem We will use %%~fa to get the full path of file.
rem Use findstr to read the file, and retrieve the
rem lines that
rem /v do not match
rem /r the regular expression
rem /c:"^$" start of line followed by end of line
rem and send the output to the temporary file
findstr /v /r /c:"^$" "%%~fa" > "%tempFile%"
rem Once we have the valid lines into the temporary
rem file, rename the temporary file as the input file
move /y "%tempFile%" "%%~fa" >nul
)
rem End - Leave the batch file before reaching the subroutine
exit /b
rem Subrotutine used to retrieve batch file information.
rem First argument (%1) will be set to the name of a variable
rem that will hold the full path to the current batch file.
:getBatchFileFullPath returnVar
set "%~1=%~f0"
goto :eof
The uncommented version
#echo off
setlocal enableextensions disabledelayedexpansion
call :getBatchFileFullPath batch
for %%a in ("%batch%") do set "folder=%%~dpa"
set "tempFile=%folder%\~%random%%random%%random%"
for %%a in ("%folder%\*") do if /i not "%%~fa"=="%batch%" (
findstr /v /r /c:"^$" "%%~fa" > "%tempFile%"
move /y "%tempFile%" "%%~fa" >nul
)
exit /b
:getBatchFileFullPath returnVar
set "%~1=%~f0"
goto :eof
I am trying to use WinRAR to compress all my different folders individually.
Example of folder content before
c:\projects\test
c:\projects\country
c:\projects\db
and after running the batch file
c:\backup\test.rar
c:\backup\country.rar
c:\backup\db.rar
I am trying the following command in a batch file. But it compresses all the folders in the projects folder being into the backup archive:
for /f "delims==" %%D in ('DIR C:\projects /A /B /S') do (
"C:\Program Files\WinRAR\WinRAR.EXE" m -r "c:\backup\projects.rar" "%%D"
)
c:\backup\projects.rar contains all the files which I want in separate archives.
How to modify the 3 lines in batch file to get the desired archives?
I think you need to change a couple things.
Change /A to /AD to get just the directories.
Remove the /S so you will only get the top-level directories in C:\Projects.
Inside your FOR loop, change the "c:\backup\projects.rar" to C:\Backup\%%D.rar"
WARNING: This code is untested.
FOR /F "DELIMS==" %%D in ('DIR C:\projects /AD /B') DO (
"C:\Program Files\WinRAR\WinRAR.EXE" m -r "C:\Backup\%%D.rar" "%%D"
)
Here is a batch file for more general usage of this common task because the folder with the subfolders to archive can be specified as parameter on running the batch file. There can be used also case-insensitive the option /N on running the batch file to suppress the execution of command PAUSE on an error occurred which could be useful on running the batch file from within a command prompt window or on calling it from another batch file.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "BackupFolder=C:\Backup"
set "FolderToArchive=C:\projects"
rem The first or the sescond argument can be optionally /N
rem to suppress the execution of command pause on an error.
set "PauseCmd=pause"
if /I "%~2" == "/N" set "PauseCmd="
if /I "%~1" == "/N" set "PauseCmd=" & shift /1
if exist "%ProgramFiles%\WinRAR\Rar.exe" goto CheckFolder
echo/
echo Error: RAR executable "%ProgramFiles%\WinRAR\Rar.exe" does not exist.
echo/
%PauseCmd%
exit /B 22
rem Folder to archive can be optionally specified as parameter.
:CheckFolder
if not "%~1" == "" set "FolderToArchive=%~1"
rem Check the existence of the folder to archive.
if exist "%FolderToArchive%\*" goto CheckDestination
echo/
echo Error: Folder "%FolderToArchive%" does not exist.
echo/
%PauseCmd%
exit /B 20
rem Check existence of backup folder and create this folder
rem if not already existing with verification on success.
:CheckDestination
if exist "%BackupFolder%\*" goto CreateArchives
md "%BackupFolder%"
if not errorlevel 1 goto CreateArchives
echo/
echo Error: Folder "%BackupFolder%" could not be created.
echo/
%PauseCmd%
exit /B 21
rem Archive each subfolder in specified or default folder to archive
rem as separate archive with name of folder as archive file name and
rem with current date and an automatically incremented number with at
rem least two digits appended to the archive file name to be able to
rem create multiple archives on different days and even on same day.
rem Parent directory path of each subfolder is removed from archive.
rem The name of the subfolder itself is added to each archive. This
rem can be changed by replacing "%%D" with "%%D\" or "%%D\*". Then
rem the files and subfolders of the compressed folder would be added
rem to archive without the name of the compressed folder.
rem Best compression is used on creating a solid archive with 4 MB
rem dictionary size. All messages are suppressed except error messages.
rem The last modification time of the created archive file is set to
rem date and time of newest file inside the archive.
:CreateArchives
set "RarError=0"
(for /D %%I in ("%FolderToArchive%\*") do (
echo Archiving %%I ...
"%ProgramFiles%\WinRAR\Rar.exe" a -ag_YYYY-MM-DD_NN -cfg- -ep1 -idq -m5 -md4m -r -s -tl -y "%BackupFolder%\%%~nI.rar" "%%I"
if errorlevel 1 call :GetRarError
)) & goto CheckRarError
:GetRarError
echo/
echo/
if %ERRORLEVEL% GTR %RarError% set "RarError=%ERRORLEVEL%"
goto :EOF
rem Wait for a key press if an error occurred on creating an archive
rem file and the option to suppress the pause on error is not used.
:CheckRarError
if not defined PauseCmd goto EndBatch
if not %RarError% == 0 %PauseCmd%
rem Exit with highest exit code of any RAR execution.
:EndBatch
exit /B %RarError%
For the details on the used switches on Rar command line open text file Rar.txt in program files folder of WinRAR which is the manual for the console version Rar.exe and read the explanations for those switches.
Note: Command a (add to archive) is used in batch code above instead of m (move to archive).
The manual for using WinRAR.exe from within a batch file can be found in help of WinRAR on tab Contents under list item Command line mode.
There are some differences on list of switches between console and GUI version of WinRAR. For example WinRAR.exe supports also creating ZIP archives which Rar.exe does not support. Therefore WinRAR.exe supports the switch -af<type> which console version does not. The switch -idq (quiet mode) of console version is switch -ibck (run in background) for GUI version.
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 /?
exit /?
for /?
goto /?
if /?
md /?
pause /?
rem /?
set /?
setlocal /?
shift /?
Note: Such an archiving can be also done with WinRAR by selecting in WinRAR the folders to archive, clicking on Add icon in toolbar, inserting C:\Backup\ on Archive name and enabling option Put each file to separate archive on tab Files. The other options used in the batch file above defined via switches can be found on the tabs General, Backup and Time.