Remove unneccessary file extensions from name - batch-file

So, I'm trying to convert a bunch of OGG files to M4A using a program called Super. Only problem is that this program adds the extension you're trying to convert to after the source extension.
So, if I convert a file named Keyboard.ogg to an M4A file, it converts it to an M4A, but the resulting file name is Keyboard.ogg.M4A.
What I want to do is when the conversion finishes, I want to run a command or batch script on every file ending in .ogg.M4A so that the result is Keyboard.m4a instead of Keyboard.ogg.M4A (The file extension should be lower case since a program I am using to develop a video game requires both .ogg and .m4a files for exports (since it uses OGG for PC exports and M4A for Mobile exports) and I think it might be case sensitive.)
I have tried the solution here, but when using %%~nf it only removes the .M4A part (instead of the .ogg.M4A) and if I were to rename that I'd be back at square 1.

Assuming none of your file names contain any additional dots other than .ogg.M4A, then all you need is a single REN command.
ren *.ogg.M4A ??????????????????????????????.m4a
Be sure to use enough ? to match the longest name in your file set.
See How does the Windows RENAME (REN) command interpret wildcards? for a full explanation of how REN handles wildcards.

#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
FOR /f "tokens=1*delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*.ogg.M4A" '
) DO (
FOR %%b IN ("%%~na") DO (
ECHO REN "%sourcedir%\%%a" "%%~nb.m4a"
)
)
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
The required REN commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(REN to REN to actually rename the files.
Take the name of each file in the source directory that fits the mask "*.ogg.m4a"
Using the name part of the filenamename, rename using the name part only +the required extension.

Related

Batch file to rename files with complex names and back again

Reviving an old topic once discussed here, as I have a similar problem. The solution proposed in the old thread worked only in half in my case.
I need first to rename various media files (mp4, mp3, wav...) with irregular, sometimes complex names as 1.mp3, 2.mp4, 3.wav, etc. And some time after I need to restore the original filenames. File extensions should remain the same in both cases.
In a more specific case of renaming .raw files Helbreder proposed two .bat scripts. The first .bat changes filenames to 1.raw, 2.raw, 3.raw, etc. and creates corresponding individual .txt files each of which keeps the original filename. The second .bat takes the original filenames from individual .txt files and renames 1.raw, 2.raw, 3.raw, etc., back to the original.
For my purpose I slightly modified the first .bat proposed, and this works perfectly well:
#echo OFF
#setlocal ENABLEDELAYEDEXPANSION
set I=1
for %%G in (*.mp3 or *.3gp or *.wav or .mp4) do (
set ORIGINAL_NAME=%%~nG
set ORIGINAL_EXTENSION=%%~xG
(
REM Try to rename file
ren "%%G" "!I!"!ORIGINAL_EXTENSION!
) && (
REM Renaming was successful
> "!I!.txt" echo !ORIGINAL_NAME!!ORIGINAL_EXTENSION!
set /A I+=1
) || (
REM Renaming was a failure
echo Cannot rename [!ORIGINAL_NAME!] file.
)
)
#endlocal
Put in a destination directory, this .bat renames all media files, keeping the correct extensions, and generates a set of .txt files each of which contains the original filename with extension.
For instance, 1.txt contains a string "Play 2019-03-06 in C.mp3" which was the original filename.
Then I need to reverse the original filenames and I run the second unmodified Helbreder's .bat. For commodity purpose I paste it here:
#echo OFF
#setlocal ENABLEDELAYEDEXPANSION
for %%F in (*.txt) do (
set BASENAME=%%~nF
REM Read original name from txt file
for /F %%G in (%%F) do (
REM iterate over all corresponding files
for %%H in (!BASENAME!.*) do (
set EXTENSION=%%~xH
REM Remove dot from extension string
set EXTENSION=!EXTENSION:~1!
if not "!EXTENSION!" == "txt" (
REM Process files
(
REM try to rename corresponding file to old name
ren "!BASENAME!.!EXTENSION!" "%%G.!EXTENSION!"
) && (
REM Operation was successful - remove TXT file
del /F /Q "%%F"
) || (
REM Something went wrong
echo Cannot restore old name for file [!BASENAME!.!EXTENSION!].
)
)
)
)
)
#endlocal
As my filenames may be complex and often include blank spaces, this second .bat works in a half-successful way.
It reverted the first original filename "Play 2019-03-06 in C.mp3" written to a 1.txt with extension, as simply "Play.mp3". It also ignored a part of the second complex filename which followed blank space, keeping only "2007-03-06.mp3" instead of "2007-03-06 output.mp3". And it successfully reverted only those filenames which were composed of numbers and underscores, without blank spaces.
As far as I understand, the issue consists in the way the second .bat retrieves the filename from the text string kept in .txt file. The first blank space occurring in the text line is considered as the end of a filename.
Could you kindly suggest a solution for reverse renaming of any files from the correspondent .txt record, which may contain letters, numbers and blank spaces (and maybe special characters, like "&" and some others).
Following Compo's advise I tried another code from the old post, this time proposed by Jeb.
After a slight modification to make it match to different file types and - important! - to keep their original extensions, the code seems to work, but with issues.
When there is more than one dot in the filename the name revert code does not restore it completely, even though it is correctly saved in the .txt file by the rename batch. For example the second batch truncates "Play 2020.10.12.mp4" to "Play 2020" and does not wish to restore the extension.
Placed in directories with many files the rename batch sometimes does not rename a part of the list, sometimes does not do the job at all and sometimes renames all files flawlessly. I first thought the partial script dysfunction might be related to the presence of special signs in the filenames, like commas or parenthesis. But no, when I delete special signs, this changes nothing. Just puzzled.
So, the new version of code is only partially solving the problem. Is there something to correct in the code, to make it more universally working? Which solution could be applied in these two cases?
I divided the code into two separate .bat files to rename and to revert original filenames.
The both follow.
Rename:
#echo off
set cnt=0
del Names.txt > nul 2>&1
echo Running Batch Rename
for %%f in (*.mp3 or *.mp4 or *.3gp or *.wav) do (
set "file=%%f"
set "EXTENSION=%%~xf"
CALL :renameToNumber
)
:renameToNumber
set /A cnt+=1
set "number=00000%cnt%"
set "number=%number:~-4%"
(echo %number% %file%) >> Names.txt
ren "%file%" %number%"%EXTENSION%"
exit /b
Revert the original names:
for /F "tokens=1,*" %%A in (names.txt) DO (
set "number=%%A"
set "filename=%%~nB"
call ren %%number%%.* "%%filename%%.*"
call echo ren %%number%%.* "%%filename%%.*"
)
exit /b

Batch extracting specific file types from master directory with many subdirectories

I have a quantity of folders with archive files,
Parent folder with subfolder eg
Graphics:
graphics 01012021/file31241.7z
graphics 01022021/file4231.7z
odds and ends 01032022/filejohnny.7z
etc
each folder contains an archive - various names numbers.
each archives contains various files, pdf's txt files invoices and image files.
Generally the images are .jpg named various names.
What I would like to do is batch attack the parent folder to extract an image file/s from the each archive from each sub directory and leave the image in the subdirectory with the archive where it came from. If the archive has multiple images that's fine, I am not targeting a single particular image.
hopefully ending up with something like
Graphics:
graphics 01012021/
file31241.7z
yellowstone.jpg
flintstone.jpg
graphics 01022021/
file4231.7z
martha.jpg
odds and ends 01032022/
filejohnny.7z
artemis.jpg
French toast.png
I would rather avoid if possible extracting all the files separating the images then having to re archive.
What I tried to discover originally was to batch extract the image files to the directory it belongs to, have the image file renamed to its directory name. I didn't get close with a solution, so I think if possible just extracting the image would be fine and I can use a renaming app to do the other I've found bulk rename utility to be just fine once I got my head around it.
You wouldn't think that over the years you would collect so many archives, like small drops they ended up become an ocean full.
I have tried researching stack and seen a lot of examples of how eg 7zip works but I just cant get my head quite around it.
I am due to retire they tell me 65 is the time for the chicken coop, I've been a pencil pusher and mouse skater most of my life in the gfx industry. I used to know what was in each archive but memory is a little how to say... rusty nowadays, I know all my archives have images in them. My life would be a lot easier in the sunset of it to look at the pictures and not have to rack my brains trying to remember what was in the archive itself.
Cheers and ty in advance from the colonies downunder.
Grumpy
I found the solution to my issue, no coding just using an app I've been using for years. Total Commander.
Solution was simple in the end.
I open up Total Commander, do a search for the archive files I want Alt F7 it will list in the right hand frame all my archives .7z .zip whatever you have.
Then you select "feed to list box" found in the bottom right hand corner. Do a Ctrl A then Alt F9 which gives you some options.
You clear unpack specific files from archive to "make sure its blank" then files to unpack tell it what your looking for in my case .jpg (it can be any specific file).
Untick unpack path names if stored with files
tick or untick overwrite existing files
untick unpack each archive to a separate subdir (name of the archive)
Hit ok.
It will then search and find the file/s you are looking for and unpack them in the directory/subdirectory/etc they are found in.
Job done... No coding just using TC.. marvellous app
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
rem The following settings for the source directory, destination directory, target directory,
rem batch directory, filenames, output filename and temporary filename [if shown] are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
SET "destdir=u:\your results"
SET "outfile=%destdir%\outfile.txt"
SET "extensions=bat txt"
SET "archives=7z zip"
CALL :prefix sdexts *. %extensions%
CALL :prefix sdarchives *. %archives%
CALL :prefix dexts . %extensions%
CALL :prefix darchives . %archives%
PUSHD "%sourcedir%"
(
FOR /f "delims=" %%b IN ('dir /b /s /a-d %sdexts% %sdarchives%') DO (
SET "unreported=%%b"
FOR %%o IN (%darchives%) DO IF /i "%%~xb"=="%%o" CALL :procarch%%o&SET "unreported="
IF DEFINED unreported ECHO %%~dpb ^| %%~nxb
)
)>"%outfile%"
popd
GOTO :EOF
:: return %1 with each other argument preceded by '%2'
:prefix
SET "$1=%1="
shift
SET "$2=%~1"
:sdl
SHIFT
IF "%1"=="" SET "%$1%"&GOTO :eof
SET "$1=%$1% %$2%%1"
GOTO sdl
:: Process .7z or .zip archives
:procarch.7z
:procarch.zip
SET "skipme=Y"
FOR /f "delims=" %%e IN ('7z L "%unreported%"') DO (
FOR /f "tokens=3delims= " %%o IN ("%%e") DO (
IF "%%o"=="------------" (
IF DEFINED skipme (SET "skipme=") ELSE (SET "skipme=Y")
) ELSE IF NOT DEFINED skipme ECHO "%%o"|FIND "D" >NUL &IF ERRORLEVEL 1 (
SET "filename=%%e"
FOR /f "delims=" %%y IN ("!filename:~53!") DO (
FOR %%c IN (%dexts%) DO IF /i "%%c"=="%%~xy" ECHO %unreported% ^| %%y
)
)
)
)
GOTO :eof
I've a similar requirement, so I spent a bit of time on this...
The first part simply sets the directories to be used.
I used bat and txt as extensions required for testing. Change as desired - just a space-separated list.
Similarly, I chose to examine .zip and .7z archives. Since 7zip can deal with both, the same subroutine can be used to process both. Other archive types may need different processing.
The code uses dir to locate the files of interest, and dir can take a series of arguments, so the routine :prefix converts the list provided as %3+ to a list in variable %1, each term prefixed by the string at %2.
So - sdexts will become *.bat *.txt and dexts .bat .txt for instance.
Next, switch to the source dir to begin the dir to list the required files. For each name returned in %%b (delims= applies the full name, /b basic list (names only), /s processes subdirectories, /a-d suppresses directorynames) - the flag unreported is set to the filename found then the extension of the filename found is compared to the darchives list. If a match is found, execute the procarch%%o routine is executed and the unreported flag set to empty. Then, if unreported has not been cleared, it's not an archive file, so report it.
procarch%%o will be resolved either procarch.7z or procarch.zip and a routine (actually the same routine) is provided.
The :prefix routine sets $1 to %1=, so for example, sdexts=. Then it shifts the parameter list and sets $2 to the prefix to be placed before each term.
Then shift again. If %1 is not empty, append a space and the prefix in $2 and %1 to $1 and repeat.
When %1 becomes empty, execute the command set "%$1%" and finish, so as $1would then contain the stringsdexts= *.bat *.txt, sdexts` would be set to the list required.
The routine :procarch.7z or procarch.zip (the first simply falls through to the second, so the same processing is executed) sets the flag skipme to non-empty as we need to skip 7z's header data.
%%e acquires each line of the 7z L report in turn. %%o is assigned the third token of the 7z report line. This will be junk up to the line with a series of dashes, then the attribute report for the archived items, then another series of dashes, then junk.
So - if %%o is a string of dashes, simply switch skipme to empty/not empty.
If %%o is not dashes, and skipme is not defined then we are between the two lines of dashes (ie. on an archived item line) so we see whether %%o contains D (which would indicate that this is a directory name, which we do not want to report). If it does not, errorlevel will be set non-zero by the find (output of the find is sent to nul=the æther) filename set to the full report line. We're not interested in the first 54 characters, but the remainder contains the archived filename, so see whether the extension of the filename found is one of interest (in dexts) and if it is, report it.
The ( on the line preceding the for ... %%b matches the )>"%outfile%" and sends all output that would otherwise go to the console to the file named.
And the ^| on the echo lines output a literal | character as | is a special character for cmd and needs to be escaped by ^ to be interpreted as a literal.
To answer your question the task is simple involving For loops with recursion, however to be robust the solution will be complex without knowing how those specific long term possibly mixed, 7zip files are subdivided, thus if a 7zip has itself two sub folders with identical named files you will hit error conditions. I have allowed for that using -aou to auto rename if necessary. however I have not added the folder name to each file as that's an extra step.
#echo off & Title Extract Images from 7z files
set "extractor=C:\Program Files (x86)\7-Zip\7z.exe"
set "archives=*.7z"
set "filetypes=*.png *.jpg *.jpeg *.tif *.tiff"
set "startDir=C:\Users\WDAGUtilityAccount\Desktop"
FOR /R "%startdir%" %%I IN (%archives%) DO ( "%extractor%" e "%%I" -o"%%~dpI" %filetypes% -aou)
You can add extra archive types such as .rar or .zip in the same way I have allowed for different image file types. HOWEVER do test for such variations first otherwise a second run will invoke that autonaming of existing duplicates. You can of course change that -aou to -aos to avoid overwite or remove it as desired.
An alternative approach on windows is that, standard windows.zip files can be navigated and thus kept as compressed folders where a click on each file will open in the default application. Thus only need extraction to the folder when you wish to use a non default app.
The secondary advantage more directly related to your need is that some viewers can read just the images and ignore any other contents (even if they can read text or html) and one I support that reads images in zips is SumatraPDF and although not listed it can open .7Z files to show in the same way
Hence my answer to the posed question is I suggest converting 7zip to standard zip rather than expand them, or use SumatraPDF as default/alternative 7z viewer !!.

Windows command line renaming files in subfolders?

I didn't find so far a similar question, so I try to explain the problem:
I have large number of files that are in subfolders inside "C:\images"
I have a list of names in two columns, so that 1st column is old filename and 2nd is a new filename. I want to change that list into a batch file.
Names are pretty unique so I want to make batch file - so that will be one command for every file to be renamed.
RENAME "C:\images\768e11ab.jpg" "4ca5d042.jpg"
RENAME "C:\images\5402c708.jpg" "b802820b.jpg"
RENAME "C:\images\1c039e0e.jpg" "80ce9797.jpg"
etc...
It is rather simple, only, files are scattered across subfolders. Is there any way to make a command so it will look for that specific file in all subfolders in "C:\images" and rename it.
Following some similar questions tried this, with no result:
for /r "C:\images\" "%%~G" (768e11ab.jpg) do "4ca5d042.jpg"
Also, tried to use some renaming application for this but they freeze when I try to rename big list of files, so I would avoid them and use batch file. Also, I would like to use this way where there is one line in batch file for every file because it is simpler for me to use it (and change it later). I appreciate your help.
Approach the problem from the other side. Instead of looping over the image files, loop over the text file.
Assuming your textfile to be something like
"768e11ab.jpg" "4ca5d042.jpg"
"5402c708.jpg" "b802820b.jpg"
"1c039e0e.jpg" "80ce9797.jpg"
Then the code could look like:
#echo off
REM read each line; %%A is the first column, %%B is the second one
for /f "tokens=1,2" %%A in (list.txt) do (
REM search the image file %%A
for /R "C:\Images\" %%C in ("%%~A") do (
REM %%C now holds the full path of %%A
ECHO ren "%%~C" "%%B~%%~xC"
)
)
If your list looks different, the tokens and perhaps the delims for the for /f loop have to be adapted.
NOTE: the ren command is just echoed for security reasons. Once you verified it does exactly what you want, remove the ECHO to enable the * ren` command.

Windows Batch - Rename files with period before extension

I'm on Windows 10, and I'm writing a batch file to convert many images from one format to another and renaming a helper file that generates more information about each image. Here's an example:
test.tif
test.tif.thing
If I'm converting to a format like png, I want to rename test.tif.thing to test.png.thing. Here's the existing script I have, which doesn't work at all due to me experimenting with numerous options, but it should hopefully highlight the problem:
for %%q in (*.tif.thing) do (
ren "%%q" "%%~pq%%~nq"
)
timeout 100
The main issue I'm having is removing the ".tif" when renaming the file, since ".thing" is technically the actual extension, so the filename is "thing.tif" without the extension. I looked into using variables to remove the characters from the string, but I never managed to get them to work, and if possible I'd like to know a cleaner solution to make this scale better should the filenames change in the future. How can I do this?
Use a second level of FOR to remove the inner extension from the file name
for %%A in (*.tif.thing) do (
REM %%A is filename.tif.thing
REM %%~nA is filename.tif
for %%B in ("%%~nA") do (
REM %%~nB is filename
ECHO ren "%%~A" "%%~nB.png.thing"
)
)
The ren command is disarmed to prevent actual renaming of files while testing the script. Remove ECHO to enable renaming.

Batch file rename reading old file name and new file name from a txt file

I have done some searching and reading but I have not been able to find a solution. I apologize if this issue is already answered on the forum. Here is what I want to do:
I have many 1000's of files that I need to rename. I can easily create a .txt file that lists the old file name and the new file name as follows:
oldfilename1.ext newfilename1.ext
oldfilename2.ext newfilename2.ext
oldfilename3.ext newfilename3.ext
etc......
The actual file names will be as follows:
TKP-RL-MB-00205-001.pdf SDY-352-20009SA10BA-RXW03-001.pdf
TKP-RL-MB-00060-004.pdf SDY-352-20010SA10BA-RXW03-004.pdf
etc....
I would like a batch file that reads the two names from the txt file and renames the file from the old name to the new name. The batch file will be located in the same directory as all the files with the old file name. I don't need functionality to check if the old file exists unless that functionality is essential to the batch file working.
I am working in Microsoft Windows 7 so I have cmd and Powershell at my disposal.
Your help is greatly appreciated.
Thank you
This should do what you have described. Remove the echo after the do when you have tested it - atm it will merely print the commands to the screen.
#echo off
for /f "usebackq tokens=1,*" %%a in ("file.txt") do echo ren "%%a" "%%b"
pause
for /f "tokens=1,2" %%a in (yourtextfile.txt) do ECHO ren "%%a" "%%b"
-assuming that the only spaces in the file are those separating the names.
Reduce %% to % to execute directly from the prompt.
The required REN commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO REN to REN to actually rename the files.
If you have that textfile, you might just put a rename at the beginning of each line and save it as .bat.
(E. g. with Notepad++, Search Mode = Extended, replace \n with \nrename, maybe check first and last lines)

Resources