Batch script, file drag&drop, change extension and reload file - batch-file

I have a batch script which accepts >=1 files via drag & drop. The full paths are kept in an array and later fed to another program as input. The file name+extension is kept in another array which is then shown to the user.
I am trying to check the file extension and if it is not .bin, automatically rename the file I dragged & dropped to .bin and reload it to be added to the two arrays. How can I do that? I have tried some if commands or %%~xi but usually it doesn't properly detect if it's .bin or not and of course the path is not updated at the array.
#echo off
pushd %~dp0
setlocal enabledelayedexpansion
set /a Count = 0
:START
set file="%~1"
if %file%=="" goto RUN
for %%i in (%file%) do set name=%%~nxi
set /a Count += 1
set [FilePath.!Count!]=%file%
set [FileName.!Count!]=%name%
shift
goto START
:RUN
for /l %%i in (1, 1, %Count%) do (
program.exe -command "![FilePath.%%i]!"
echo.
echo File Name: ![FileName.%%i]!
echo.
pause
cls
if exist file.log del file.log
)

You could just rename it during your array population. There are a few other potential problems with your script (such as pushd to an unquoted directory, delayedexpansion where you don't need it where it will potentially clobber filenames containing exclamation marks, and if %file%=="" should have "%file%" quoted). And there's really no reason to maintain an array of filenames or loop twice. Your script is much more complicated than it needs to be.
#echo off
setlocal
pushd "%~dp0"
for %%I in (%*) do (
if /I not "%%~xI"==".bin" move "%%~fI" "%%~dpnI.bin" >NUL
program.exe -command "%%~dpnI.bin"
echo;
echo File Name: "%%~nxI"
echo;
rem If you want to rename the file back the way it was after running
rem program.exe on it, uncomment the following line:
rem if /I not "%%~xI"==".bin" move "%%~dpnI.bin" "%%~fI" >NUL
pause
cls
if exist file.log del file.log
)

Related

Backup a File or Folder when dropping it on the same bat

So I've managed to cobble together a script witch works as intended for files when using "copy". It creates a backup folder "_OLD" and makes an iterated (file001, file002, etc) copy of the file I dropped on my bat by checking for the highest version in the backup folder. How ever I would like to have only one bat that would work the same way for both a file or folder. By substituting "copy" with "xcopy" I managed to copy the folder but now the file wont be copied at all. I know a little bit of programing but I'm not very experienced with bat scripts. Is there an easy fix to make it work the same on both a file and folder?
#echo off
rem set this to whatever you like
set "BackupFolderName=_OLD"
rem splits filename into name and extension etc for processing
set "OutputFolder=%CD%\%BackupFolderName%"
set "FullPath=%~1"
set "Filename=%~n1"
set "Ext=%~x1"
rem creates an output folder if none exist
if not exist "%OutputFolder%" mkdir "%OutputFolder%"
rem find the highest version of the file
set a=1
set pad=00000
:loop
rem leading zeroes
SET b=%pad%%a%
rem %var:~10% gets the sub-string from index 10 to the end of %var%
SET b=%b:~-3%
if exist "%OutputFolder%\%Filename%%b%%Ext%" set /a a+=1 && goto :loop
echo "Backed up %FilenameExt% as %Filename%%b%%Ext% in %BackupFolderName%"
xcopy /s/y "%FullPath%" "%OutputFolder%\%Filename%%b%%Ext%"
rem pause
timeout 1 >nul
exit
Here is my final code that takes multiple files or folders and does a backup of them:
#echo off
setlocal
rem set this output folder name to whatever you like eg _OLD
set "BackupFolderName=_OLD"
rem creates an output folder, if none exist
set "OutputFolder=%CD%\%BackupFolderName%"
if not exist "%OutputFolder%" mkdir "%OutputFolder%"
rem loops through all the files dropped on bat
FOR %%G IN (%*) DO (call :sub %%G)
goto :end
:sub
rem splits filename into name and extension etc for processing
set "FullPath=%~1"
set "Filename=%~n1"
set "Ext=%~x1"
rem rem find the highest version of the file
set a=1
set pad=00000
:loop
rem leading zeroes
SET b=%pad%%a%
rem %var:~10% gets the sub-string from index 10 to the end of %var%
SET b=%b:~-3%
if exist "%OutputFolder%\%Filename%%b%%Ext%" set /a a+=1 && goto :loop
rem rem checks if dropped item is file or folder
set type=invalid
for %%F in ("%~1") do (echo/%%~aF|findstr /bc:"d" >nul && set type=folder)
for %%F in ("%~1") do (echo/%%~aF|findstr /bc:"-" >nul && set type=file)
rem copies file or folder to destination
if %type%==file (copy "%FullPath%" "%OutputFolder%\%Filename%%b%%Ext%" >nul)
if %type%==folder (xcopy /s/y/q "%FullPath%" "%OutputFolder%\%Filename%%b%%Ext%\" >nul)
echo "Backed up %Filename% as %Filename%%b%%Ext% in %BackupFolderName%"
goto :eof
:end
pause
rem timeout 1 >nul
rem exit
You can check the file attributes (see for /?)
#echo off
setlocal
set type=invalid
for %%F in ("%~1") do (echo/%%~aF|findstr /bc:"d" >nul && set type=folder)
for %%F in ("%~1") do (echo/%%~aF|findstr /bc:"-" >nul && set type=file)
echo %type%

batch script - find and replace line that starts with specific value in an .ini file

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 /?

Remove duplicate files in a directory

I have a working script, (below), which compares files, by size only, and if one or more of the files have different size, it shows on the .bat screen.
#echo off
setlocal EnableDelayedExpansion
rem Group all file names by size
for /R %%a in (*.*) do (
set "size[%%~Za]=!size[%%~Za]!,%%~Fa"
)
rem Show groups that have more than one element
for /F "tokens=2,3* delims=[]=," %%a in ('set size[') do (
if "%%c" neq "" echo [%%a]: %%b,%%c
)
pause
But I need more!
I also need the script delete duplicate files, keeping just one. For example, if there are 3 files of the same size but with different names, the script should choose one to keep, deleting the other 2.
#LotPings, i tried with 2 .pdf files, and appeared this message in the pic below:
#LotPings
Now it recognized fine! But it doesn't deleting the duplicate, just recognizing.... Look the image below:
I think treating files with same size as same content is a bit naive.
If in doubt better do a binary compare with fc.
Your way of stuffing %%~Fa into a string without quoting every single name possibly containing spaces can be problematic in further processing.
If the files are identical you could create links.
You know that for /r will recurse into subdirs?
The following batch will process the size[] array differently passing the size and content to a subroutine which keeps the first file and (only echos) the del command.
:: Q:\Test\2018\06\06\SO_50723488.cmd
#echo off & setlocal
rem Group all file names by size
for /R %%a in (*.*) do call set size[%%~Za]=%%size[%%~Za]%%,"%%~Fa"
rem Process groups
for /F "tokens=2* delims=[]=," %%a in ('set size[') do Call :Sub %%a %%b
pause
Goto :Eof
:Sub
If "%~3"=="" (Set "size[%1]="&goto :EOf)
Echo ========================================
Echo processing %*
Echo Keep %2
Shift&shift
:loop
Echo Del %1
if not "%~2"=="" (shift&goto :loop)
Sample output:
> Q:\Test\2018\06\06\SO_50723488.cmd
========================================
processing 0 "Q:\Test\2018\05\03\Text3.txt","Q:\Test\2018\05\27\log.html"
Keep "Q:\Test\2018\05\03\Text3.txt"
Del "Q:\Test\2018\05\27\log.html"
========================================
processing 14 "Q:\Test\2018\05\03\Text1.txt","Q:\Test\2018\05\15\HP-G1610-20180515.json"
Keep "Q:\Test\2018\05\03\Text1.txt"
Del "Q:\Test\2018\05\15\HP-G1610-20180515.json"
========================================
processing 21 "Q:\Test\2018\05\12\text1.txt","Q:\Test\2018\05\12\text2.txt"
Keep "Q:\Test\2018\05\12\text1.txt"
Del "Q:\Test\2018\05\12\text2.txt"
========================================
processing 22 "Q:\Test\2018\05\20\2.txt","Q:\Test\2018\05\22\version.ps1"
Keep "Q:\Test\2018\05\20\2.txt"
Del "Q:\Test\2018\05\22\version.ps1"
========================================
processing 288 "Q:\Test\2018\05\11\RawData.txt","Q:\Test\2018\05\23\SO_50478080.ps1"
Keep "Q:\Test\2018\05\11\RawData.txt"
Del "Q:\Test\2018\05\23\SO_50478080.ps1"
The following script removes duplicate files in the current directory. It leaves one file, and removes rest of its duplicates. I developed the script for Windows 10, so it might not work for other Windows versions.
The advantage of this script is it not only checks the last modified date and time, but also the file size. Let's say you have a text file with *** symbols? you can turn them all ### symbols, and still occupy the same space. The script checks the last modified date, and time along with its size to ensure both the files are identical, otherwise it doesn't remove any file.
setlocal enabledelayedexpansion
echo(
echo "This program removes duplicate files in the current directory."
echo "Warning: Take a backup of the current directory to avoid accidents"
PAUSE
echo(
set path=%cd%
set /A count=0
for %%a in (*.*) do (
for %%b in (*.*) do (
if exist "%%b" if %%a neq %%b (
if "%%~Ta %%~Za" equ "%%~Tb %%~Zb" (
echo "%%a File is deleted"
set /A count+=1
del "%%a"
)
)
)
)
echo(
echo "---------"
echo "!count! Duplicate Files were deleted in the current directory"
echo "---------"
echo(
endlocal
PAUSE
If you have any problems report me at
https://github.com/donqq/Duplicate-File-Remover/

Parsing with a FOR command in a .BAT file

I'm having a bit of trouble with a FOR DO command in a .BAT file I'm working on for work.
Here is the entire code I'm working with
SET parent="%~dp0"
SET GroomedDir="%~dp0Groomed\"
XCOPY /s/e/y Groomed %parent%NewGroomed\
CD NewGroomed
setlocal enabledelayedexpansion
FOR %%i in (IMG_*.jpg) DO (
SET OldName=%%i
SET ImgNumber=!OldName:~4,-4!
SET DBLookup=FINDSTR !ImgNumber! Database.txt
!DBLookup! > return.txt
FOR /F "tokens=1-5 delims=|" %%J in (return.txt) do (
REN !OldName! "%%K_%%L.jpg"
MKDIR %%M\%%N
MOVE "%%K_%%L.jpg" %%M\%%N
)
)
del return.txt
endlocal
cd ..
ren Groomed "Groomed Backup"
ren NewGroomed Groomed
The trouble come in lines 12-14 (I put in line separators). I can't seem to put the variable %DBLookup% into the FOR command, and am forced to use a placeholder text file instead. It works, in the end, but wouldn't it be better to save myself the write to return.txt operation, and the read return.txt operation?
For context, return.txt contains a single line from of text like this:
115525|Last_First|5233|8|Teacher
I use the FOR command because it allows me to delimit using the pipe character, or whatever else, and output to %%J %%K %%L %%M and %%N variables.
Any help or advice for this relative newcomer is much appreciated!
Here's my code with my comments:
REM THESE FOUR LINES:
REM 1) SET A VARIABLE FOR THE PARENT DIRECTORY LOCATION,
REM 2) SET A VARIABLE FOR THE GROOMED DIRECTORY,
REM 3) COPY THE GROOMED DIRECTORY TO "NEWGROOMED\",
REM 4) CHANGE THE LOCATION TO BE WORKING ENTIRELY WITHING NEWGROOMED\
SET parent="%~dp0"
SET GroomedDir="%~dp0Groomed\"
XCOPY /s/e/y Groomed %parent%NewGroomed\
CD NewGroomed
REM THIS FOR LOOP LOADS ALL JPGS IN THE \NEWGROOMED\ DIRECTORY THAT BEGIN WITH THE STRING, "IMG_"
setlocal enabledelayedexpansion
FOR %%i in (IMG_*.jpg) DO (
SET OldName=%%i
REM THIS LINE COPIES THE OLD NAME MINUS THE FIRST FOUR CHARACTERS, "IMG_", AND MINUS THE EXTENSION (LAST 4 CHARS)
SET ImgNumber=!OldName:~4,-4!
REM THESE NEXT TWO LINES LOOK UP OUR IMAGE NUMBER IN DATABASE.TXT AND RETURN THE ENTIRE LINE TO A NEW FILE CALLED RETURN.TXT
SET DBLookup=FINDSTR !ImgNumber! Database.txt
!DBLookup! > return.txt
REM NOW WE PARSE RETURN.TXT USING PIPE DELIMITERS INTO THE VARIABLES J,K,L,M,N (ID,Name,IMG#,Grade,Homeroom)
FOR /F "tokens=1-5 delims=|" %%J in (return.txt) do (
REN !OldName! "%%K_%%L.jpg"
MKDIR %%M\%%N
MOVE "%%K_%%L.jpg" %%M\%%N
)
)
del return.txt
endlocal
cd ..
ren Groomed "Groomed Backup"
ren NewGroomed Groomed
Overall, my goal is to begin with a folder, "Groomed," with a bunch of images titled as such: IMG_####.jpg.
My batch file will:
1) create a backup of the entire starting directory
2) rename each image according to the database.txt file
3) move each renamed image into a new grade/teachername folder
I am starting with a file, (database.txt) that comes to me from another employee. The file is a plain list for each student in the following format: student id|lastname_firstname|image#|grade#|teachername.
As i mentioned. The file works perfectly, but since I'm new to batch files I was feeling like it might be dumb of me to write to a throwaway file just to save a string and then delete it. That's what variables are for, but I was having a hard time getting that variable to pass into the FOR command.
sample of Database.txt
659968|Saperstein_Ryan|4603|7|Hallock
015520|Qian_Emily|2528|7|Hallock
528852|Rizzo_Jason|4618|7|Krukowski
and a few filenames I'm starting with:
IMG_2528.jpg
IMG_4544.jpg
IMG_7044.jpg
IMG_6880.jpg
IMG_4839.jpg
Edit:
A first bunch by parsing database.txt first and then compare by using if exist. The second is by comparing variables
code:
rem create a sample of the following example
rem :: student id|lastname_firstname|image#|grade#|teachername
rem :: The common points are only in the first 3 jpg
copy nul IMG_4603.jpg
copy nul IMG_2528.jpg
copy nul IMG_4618.jpg
copy nul IMG_4619.jpg
copy nul IMG_4620.jpg
copy nul IMG_4630.jpg
(
echo 659968^|Saperstein_Ryan^|4603^|7^|Hallock
echo 015520^|Qian_Emily^|2528^|7^|Hallock
echo 528852^|Rizzo_Jason^|4618^|7^|Krukowski
echo 528817^|Rizzo_Jas17^|4617^|7^|Krukows17
echo 528816^|Rizzo_Jas16^|4616^|7^|Krukows16
)>sample.txt
rem :: type sample.txt
rem :: pause
Method #1
#echo off
setlocal enabledelayedexpansion
for /f "tokens=1-5 delims=|" %%a in (sample.txt) do (
set "student_id=%%a"
set "student_name=%%b"
set "student_image=%%c"
set "student_grade=%%d"
set "student_teacher=%%e"
rem :: echo !student_name!_!student_image!.jpg
if exist "IMG_!student_image!.jpg" (
rem :: remove echo in the following lines if it's okay.
echo:
echo ren "IMG_!student_image!.jpg" "!student_name!_!student_image!.jpg"
echo mkdir "!student_grade!\!student_teacher!"
echo move "!student_name!_!student_image!.jpg" "!student_grade!\!student_teacher!"
)
)
Method #2
#echo off
setlocal enabledelayedexpansion
for %%i in (IMG_*.jpg) do (
set "OldName=%%~i"
set "image_number=!OldName:~4,-4!"
rem :: echo image_number: !image_number!
for /f "tokens=1-5 delims=|" %%b in (
'findstr !image_number! sample.txt'
) do (
set "student_id=%%a"
set "student_name=%%b"
set "student_image=%%c"
set "student_grade=%%d"
set "student_teacher=%%e"
if "!student_image!"=="!student_image!" (
rem :: remove echo in the following lines if it's okay.
echo:
rem :: echo !image_number! = !student_image!
echo ren "IMG_!student_image!.jpg" "!student_name!_!student_image!.jpg"
echo mkdir "!student_grade!\!student_teacher!"
echo move "!student_name!_!student_image!.jpg" "!student_grade!\!student_teacher!"
)
)
)
output:
ren "IMG_2528.jpg" "Qian_Emily_2528.jpg"
mkdir "7\Hallock"
move "Qian_Emily_2528.jpg" "7\Hallock"
ren "IMG_4603.jpg" "Saperstein_Ryan_4603.jpg"
mkdir "7\Hallock"
move "Saperstein_Ryan_4603.jpg" "7\Hallock"
ren "IMG_4618.jpg" "Rizzo_Jason_4618.jpg"
mkdir "7\Krukowski"
move "Rizzo_Jason_4618.jpg" "7\Krukowski"

Batch File Loop Skip File if name contains

I am creating this batch file, that works with handbrakecli, to batch convert avi to mp4.
However I am stuck in how to continue the loop and skip the current file inside a loop.
FOR /R "%somepath%" %%G in (*.avi) DO (
rem skip if filename contains word trailer
rem skip if file name contains word sample
rem do conversion
)
This currently doesn't work in skipping the files that contain trailer or sample
I have tried using find or findstr and both fail to skip.
echo "%%G" | c:\windows\system32\findstr /i "trailer" > NUL
If %ERRORLEVEL% EQU 1 set skip Yes
Here is for sample.
echo "%%G" | c:\windows\system32\findstr /i "sample" > NUL
If %ERRORLEVEL% EQU 1 set skip Yes
If a file contains either trailer or sample, I do not want to do any handbrakecli conversions, but to just skip it.
I do echo's to display which files get converted, and it does include files with Sample or sample in the name.
I have tried using find or findstr and both fail to set skip to yes
if skip == No do ( rem do conversion )
I only want to convert non-trailer/sample avi files.
Thank you for your time.
try this, put your conversion commands in the loop and remove the word echo before handbrakecli if the output is OK:
#echo off &setlocal
FOR /R "%somepath%" %%G in (*.avi) DO (
set "fpath=%%G"
set "fname=%%~nG"
setlocal enabledelayedexpansion
if "!fname!"=="!fname:trailer=!" if "!fname!"=="!fname:sample=!" (
echo handbrakecli.exe "!fpath!" &rem put your conversion command here
>>"logfile.log" echo !fname!
)
endlocal
)
The file name+file path is in the variable "!fpath!".
Added some code concerning the needs of the OP:
#echo off &setlocal
rem replace avi with mp4 files in my movie folder
rem grab 4 random folders with avi in them and no mp4
rem Settings for this Batch File
set "moviepath=H:\Movies"
set "logfile=C:\Documents and Settings\%USERNAME%\LogFiles\avi_converter.log"
rem check if log file exists
if not exist "%logfile%" echo(>"%logfile%"
rem create empty convert file
copy nul "convert_movies.bat" >nul 2>&1
rem add echo off
echo #echo off >>"convert_movies.bat"
rem set counter
SET /A COUNT=1
FOR /R "%moviepath%" %%G in (*.avi) DO (
set "fpath=%%~fG"
set "fname=%%~nG"
setlocal enabledelayedexpansion
rem check if count greater than 4
if !COUNT! gtr 4 goto:eof
if "!fname!"=="!fname:trailer=!" if "!fname!"=="!fname:sample=!" (
rem echo handbrakecli.exe "!fpath!" &rem put your conversion command here
rem Send File To HandBrakeCLI
CALL :DOHandBrakeCLI "!fpath!"
rem Delete File
CALL :DeleteOldFile "!fpath!"
rem Add Log Entry
CALL :LogEntry "!fpath!"
rem add line break space
echo( >>"convert_movies.bat"
endlocal
rem increment counter
SET /A COUNT+=1
) else endlocal
)
rem end main program, to close cmd window replace it with EXIT
goto:eof
:DOHandBrakeCLI
rem skip if the parameter is empty
IF "%~1"=="" goto:eof
For %%A in ("%~1") do (
Set "Folder=%%~dpA"
Set "Name=%%~nxA"
)
rem echo %Folder%%Name%
echo start /b "" "c:\handbrakecli\HandBrakeCLI.exe" -i "%~1" -o "%Folder%%~n1.mp4" --preset="High Profile">>"convert_movies.bat"
exit /b
:DeleteOldFile
rem skip if the parameter is empty
IF "%~1"=="" goto:eof
For %%A in ("%~1") do (
Set "Folder=%%~dpA"
Set "Name=%%~nxA"
)
rem sends parameters to deletefile which will make sure new file exists before deleting old one
echo c:\projects\deletefile.bat "%~1" "%Folder%%~n1.mp4">>"convert_movies.bat"
exit /b
:LogEntry
rem skip if the parameter is empty
IF "%~1"=="" goto:eof
echo "%~1">>"%logfile%"
exit /b
This should work:
#echo off
FOR /R "%somepath%" %%G in (*.avi) DO (
echo "%%~nG" |findstr /i "trailer sample">nul || (
rem do conversion
)
)
It's difficult to see where your post is pseudocode and where actual code.
The first sample contains only REM statements, so it's not surprising it apparently does nothing.
Your second and third sample are effectively identical - the only difference is the target string. It's not surprising that the variable skip isn't set to Yes since the correct syntax is
if %errorlevel% equ 0 set skip=Yes
The syntax you've posted will REPORT that skip is not defined - it ignores the Yes
HOWEVER this syntax is only usable OUTSIDE of a "block statement" - that is, a multiple-instruction statement (enclosed in parentheses) or cascaded&by&ampersands. Batch first PARSES a complete statement - from the FOR or if through to the appropriate closing-parenthesis and THEN executes it. As part of the PARSING phase, any %var% - including %errorlevel% is replaced by its value as it stands at the time the entire statement is parsed - not as it changes due to the operation of the for.
In order to use the value as it changes, you need to use
if errorlevel 1 (do_something) else (do_something_else)
where do_something and do_something_else) may themselves be compound statements.
OR
if defined variable (do_something) else (do_something_else)
where the variable either is defined or not
OR
setlocal enabledelayedexpansion
....
if !errorlevel! equ x (do_something) else (do_something_else)
OR
if !var! neq something (do_something) else (do_something_else)
But it's quite possible that
FOR /R "%somepath%" %%G in (*.avi) DO (
echo(%%G|findstr /i "sample trailer" >nul
if errorlevel 1 echo %%G
)
will give you an appropriate skeleton.
Echo the filename through FINDSTR and look for "sample" or "trailer" /i case-insensitive. Findstr sets errorlevel 0 if either target string is found, 1 otherwise - and the if errorlevel x syntax works on the dynamic value of errorlevel within a loop.
#ECHO on &SETLOCAL
REM This script was inspired by Endoro's expanded script
(https://stackoverflow.com/a/16891696/10572786).
REM This batch script will recursively search for all .mp4 files that don't
have (x265) in the file name. Any valid results will be encoded with x265
using FFmpeg. The original .mp4 file will remain unchanged in it's original
folder with the new x265 version.
REM Example: %PATH%\A.mp4 > %PATH%\A(x265).mp4
REM If you don't have ffmpeg.exe on your PC you must download or build it
with Microsoft Visual Studios. I recommend you download and run media
autobuild suite on GitHub: (https://github.com/jb-alvarado/media-
autobuild_suite).
REM Once ffmpeg is compiled/downloaded make sure to set it's folder path as
an environmental variable in Windows before running the script. Change the
script's working directory to your .mp4 files root folder using the "cd"
command.
REM !!BEGIN SCRIPT!!
cd /d %USERPROFILE%\Desktop\Vids\
REM or perhaps use [cd /d %OneDrive%\Desktop\Vids]
REM Set mp4PATH to the root folder you wish to recursively search.
SET "mp4PATH=%USERPROFILE%\Desktop\Vids\"
REM Create empty convert file.
COPY NUL "convert_movies.bat" >NUL 2>&1
REM Add ECHO off.
ECHO #ECHO off >>"convert_movies.bat"
REM Recursively search root folder.
FOR /R "%mp4PATH%" %%G IN (*.mp4) DO (
SET "fpath=%%~fG"
SET "fname=%%~nG"
SETLOCAL enabledelayedexpansion
REM Ignore all files that have "(x265)" in the file name.
IF "!fname!"=="!fname:*(x265)=!" (
CALL :DO_FFmpeg_CLI "!fpath!"
ECHO(>>"convert_movies.bat"
) ELSE ENDLOCAL
)
)
GOTO:EOF
REM CALL variables for use in FFmpeg's command line.
:DO_FFmpeg_CLI
IF "%~1"=="" GOTO:EOF
FOR %%I IN ("%~1") DO (
SET "Folder=%%~dpI"
SET "Name=%%~nxI"
)
REM Export info to "convert_movies.bat and run ffmpeg.exe's command line in the cmd.exe window.
ECHO ffmpeg -y -i "%~1" -c:v libx265 -preset slow -crf
18 -c:a aac "%Folder%%~n1(x265).mp4">>"convert_movies.bat" && ffmpeg |
ffmpeg -y -i "%~1" -c:v libx265 -preset slow
-crf 18 -c:a aac "%Folder%%~n1(x265).mp4"
EXIT /B
PAUSE
The Batch file below solve the original question AND limit the number of converted files to a given number (that does not appear in the original question):
#echo off
setlocal EnableDelayedExpansion
rem Insert in the next line the list of files to skip
set skip=/trailer/sample/
set count=0
FOR /R "%somepath%" %%G in (*.avi) DO (
if /I "!skip:/%%~nG/=!" equ "%skip%" (
echo Current file name is not in skip variable
echo Do conversion on: %%G
set /A count+=1
if !count! equ 20 goto :endLoop
)
)
:endLoop
echo Converted files: %count%

Resources