How to remove a prefix from multiple files? - batch-file

I downloaded a lot of videos that are named like [site.com] filename.mp4 and I wanted to remove the prefix so that they are named like filename.mp4.
I tried a batch file with the following code:
ren "[site.com] *.mp4" "///////////*.mp4"
But the result was .com] filename.mp4 and can't rename anything beyond the dot, any ideas?

#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
FOR /f "tokens=1*delims=]" %%a IN (
'dir /b /a-d "%sourcedir%\*" '
) DO IF "%%b" neq "" (
FOR /f "tokens=*" %%h IN ("%%b") DO ECHO(REN "%sourcedir%\%%a]%%b" "%%h"
)
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.
Perform a directory scan of the source directory, in /b basic mode /a-d without directories and tokenise each filename found - the part before the first ] to %%a and the remainder to %%b.
If %%b is not empty (ie. did not contain ]) then do nothing, therwise use the default token set (which includes space) and tokens=0 to strip the leading spaces from %%b into %%h, then build the original filename and rename.

Use a for loop to split on the space in the name.
#echo off
:: Pass the file name in as an argument.
:: Split the full path into a directory and filename in case the folder has a space too
set "filepath=%~dp1"
set "filename=%~nx1"
:: Jump into the hosting directory, split the file name after the first space, and jump out
pushd %filepath%
for /f "tokens=1,*" %%A in ("%filename%") do ren "%filename%" "%%B"
popd

Just for completeness, a cmd.exe alternative:
For %A In ("*] *.*") Do #(Set "_=%A"&Call Ren "%A" "%_:*] =%")

Use parameter expansion with pattern replacement.
f='[site.com] filename.mp4'
mv "$f" "${f/\[site\.com\] /}"
Even Windows systems can execute a Bash.
http://www.mingw.org/wiki/msys
This is a for loop:
for f in *.mp4; then
mv "$f" "${f/\[site\.com\] /}"
done

Related

How do I replace spaces and symbols in all files and FOLDERS with a batch file

I'm very close I think. I have a folder where-in I'm trying to rename all the sub folders and files such that caps are stripped, symbols replaced with applicable words, and spaces changed to hyphens in both the files AND their parent sub-folders.
Here's the batch file I have so far:
cd d:\scripts\testing\
for /r %%D in (.) do #for /f "eol=: delims=" %%F in ('dir /l/b "%%D"') do #ren "%%D\%%F" "%%F"
SET location=d:\scripts\testing\
for /R %location% %%A in (*.*) do call :replspace "%%A"
for /R %location% %%A in (*.*) do call :repland "%%A"
goto :eof
:replspace
set "_fn=%~nx1"
ren %1 "%_fn: =-%"
:repland
set "_fn=%~nx1"
ren %1 "%_fn:&=and%"
As you might be able to see, first it goes through and renames everything (files and folders) in d:\scripts\testing\ to lower-case. Next it renames all files in that same directory to replace spaces with hyphens and "&" with the word "and". This all works... except I need to do the same symbol and space changes to the folders and I'm not finding any real info on how to do that.
Anyone have any suggestions?
BTW, this runs on server 2012 r2, however for interoperability issues, the scripts have to be old fashioned batch scripts.
You can perform the entire replacement task with one for loop., by using dir /s to recursively search the directory.
#echo off
setlocal enabledelayedexpansion
pushd "d:\scripts\testing\" || goto :EOF
for /f "delims=" %%i in ('dir /b /l /s') do (
set "item=%%~i"
set "item=!item:%%~dpi=!"
set "item=!item: =-!"
ren "%%~fi" "!item:&=and!"
)
popd
I did not set the & replacement as a variable seeing as there are only two replacements done, so simply using the substitution on the last item makes sense without the need to set again. If you have more replacements to add, add them before the ren line:
Note that this example will merely echo the results for testing purpose. Only remove echo once you're convinced the results are as expected.
Then, take note of || goto :EOF in the pushd statement. This is critical for good reason. Should it fail to cd or pushd, generally the script will continue with the rename, from the working directory it was started in, or a previous cd pushd etc. In this case, if it fails to find the directory, or it does not have permission, it will skip the remainder of the script entirely.
Final Note. Should your files or folders contain ! this will need to change. You can then simply revert to moving the set and ren to a label, then call the label as delayedexpansion will cause the ! to be lost.
While Gerhard's script is clean and should work, it trips on itself under certain circumstances like mine. I wound up using this script:
rem #### Step 1: move to working directory ####
cd "d:\scripts\testing\"
rem #### Step 2: change case on everything ####
for /r %%D in (.) do #for /f "eol=: delims=" %%F in ('dir /l/b "%%D"') do #ren "%%D\%%F" "%%F"
rem #### Step 3: set location ####
SET location=d:\scripts\testing\
for /R %location% %%A in (*.*) do call :replspace "%%A"
for /R %location% %%A in (*.*) do call :repland "%%A"
rem #### Step 4: replace spaces/symbols on directories ####
setlocal enabledelayedexpansion
pushd "D:\scripts\testing\" || goto :EOF
for /f "delims=" %%i in ('dir /l /b /s /ad') do (
set "item=%%~i"
set "item=!item: =-!"
move "%%~fi" "!item:&=and!"
)
popd
rem #### variables ####
:replspace
set "_fn=%~nx1"
ren %1 "%_fn: =-%"
:repland
set "_fn=%~nx1"
ren %1 "%_fn:&=and%"
Its a combination of my own script and a slight modification of Gerhard's script. Bassically I ended up stepping through the modifications.
change everything to lower case.
replace spaces and symbols in the file names.
replace spaces and symbols in the directory names.
I know it's repetitive and I'd like to do it with less lines, but it works.

Search file with wildcard path

I want to write a script to prompt user for file path and list all files found. The file path can contain wildcards. Something similar to this. But the batch script version of it. For example:
C:\Somewhere\user*\app\version-*.*\start.exe
The files might be located like this:
C:\Somewhere\user345\app\version-1.0\start.exe
C:\Somewhere\user898\app\version-1.2\start.exe
C:\Somewhere\user898\app\version-1.3\start.exe
I tried to use FOR and it turns out to be so much harder than expected because FOR does not support wildcards in the middle of a path.
Is there a way to list these files? (Maybe without using for?)
I think this recursive solution works pretty well; you may name it WCDIR.bat:
#echo off
setlocal
if "%~1" neq "" set "next=%~1" & goto next
echo Show files selected by several wild-cards
echo/
echo WCDIR wildcardPath
echo/
echo Each folder in the path may contain wild-cards
echo the last part must be a file wild-card
goto :EOF
:next
for /F "tokens=1* delims=\" %%a in ("%next%") do set "this=%%a" & set "next=%%b"
if defined next (
for /D %%a in ("%this::=:\%") do (
setlocal
cd /D "%%~a" 2>NUL
if not errorlevel 1 call :next
endlocal
)
) else (
for /F "delims=" %%a in ('dir /B /A:-D "%this%" 2^>NUL') do echo %%~Fa
)
exit /B
EDIT: I fixed a small bug in the last for /F command.
For example, the output of WCDIR.bat C:\Windows\Sys*\find*.exe command in my Windows 8.1 64-bits computer is:
C:\Windows\System32\find.exe
C:\Windows\System32\findstr.exe
C:\Windows\SysWOW64\find.exe
C:\Windows\SysWOW64\findstr.exe
You can try with the command Where /?
The WHERE command is roughly equivalent to the UNIX 'which' command. By default, the search is done in the current directory and in the PATH.
#echo off
Where /R "%programfiles%" *winrar.exe
pause
#echo off
:: Example d'input
set UserInput=*drive*
:: building the Pattern
set cmd=%Userinput%.exe
:: storage Where.exe command in a macro, the execution will be faster
set whereCmd=where.exe /r c:\windows\ %cmd%
:: execution of macro and output formatting
for /f %%a in ('%whereCmd%') do echo %%~nxa --^> %%a
pause

copy & rename files to other folder

I have some of log files formatted like this "name.log"
I would like to copy those from one folder to another folder like
xcopy /y "C:\Folder1" "D:\Folder2"
And i need to rename file with created date of original file (no copy file) so that the text file in Folder2 would be like "name yyyymmddhhmm.log" if some file has the same name (date of creation) it will be overwritten.
The code:
set Source=C:\Users\user1\Desktop\Folder1
set Dest=D:\Folder2
if not exist %Dest% md %Dest%
for /F %%a in ('dir /b "%Source%\*.txt"') do call :Sub %%a
goto :eof
:Sub
set "filename=%1"
for /F %%s in ("%Source%\%1") do if %%~zs==0 goto :eof
set "datepart="
FOR /F "tokens=1-5 delims=/-: " %%a IN ('dir /tc "%filename%" ^| findstr "%filename%"') DO (
IF "%%c" neq "" SET "datepart=%%c%%a%%b%%d%%e"
)
FOR /F %%a IN ("%filename%") DO (
set "NewName=%%~na %datepart%%%~xa"
)
xcopy /y "%Source%\%filename%" "%Dest%\%NewName%*"
GOTO :EOF
The problem is that If I don't put the .bat in the same folder that origin files (Folder1),the files aren't change name. For example, if it is out, the files change name with old name and one white space.
The command windows tell me that it doesn't find the file when it get the creation date.
If I put the script into folder1 it works well.
On the other hand, if I execute the script with "Task Scheduler" I have the same problem. The files are copied but without date of creation.
What do I need to solve this problem?
#ECHO OFF
SETLOCAL
set Source=C:\Users\user1\Desktop\Folder1
set Dest=D:\Folder2
set "Source=u:\sourcedir\t w o"
set "Dest=u:\destdir"
if not exist "%Dest%" md "%Dest%"
for /F "delims=" %%k in ('dir /b "%Source%\*.log"') do call :Sub "%%k"
goto :eof
:Sub
SET "newname=%~1"
for /F "delims=" %%s in ("%Source%\%~1") do (if %%~zs==0 goto :eof
FOR /F "tokens=1-5 delims=/-: " %%a IN ('dir /tc "%Source%\%~1" ^| findstr "%~1"') DO (
IF "%%c" neq "" SET "newname=%%~ns %%c%%a%%b%%d%%e%%~xs"
)
)
ECHO(xcopy /y "%Source%\%~1" "%Dest%\%NewName%"
GOTO :EOF
The required XCOPY commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(XCOPY to XCOPY to actually copy the files. Append >nul to suppress report messages (eg. 1 file copied)
This may seem quite a radical change, but actually it really isn't.
First issue is that I overrode your directory settings with directories to suit my system. The syntax SET "var=value" (where value may be empty) is used to ensure that any stray trailing spaces are NOT included in the value assigned. set /a can safely be used "quoteless".
Using quotes in the md command makes the procedure immune to "paths containing separators" - I test using spaces in paths and filenames because that appears to be a popular thing to do.
I changed the directory-scan metavariable from %%a to %%k to avoid confusion with the %%a in the subroutine. Your text says that you are starting with &.log files, but your filemask was *.txt so I changed it to *.log. Quoting the parameter delivered to :Sub means the procedure will receive the entire name of the file if it contains spaces.
Within the subroutine, it would appear that yowant no name-change if the %%c part from the dir/tc scan is empty. %~1 is the supplied filename minus the quotes.
The outer loop in %%s : I added delims= to cater for spaces in filenames and used %~1 in preference to %filename%
Within the %%s block, %%s refers to the file, so you can use %%s and its modified forms like %%~zs to refer to that file's characteristics - which unfortunately do not include create-date (%%~ts contains the last-update date - you may be able to use that in te following line rather than dir and findstr)
Then as #aschipfi suggested, include the source directory in the dir otherwise the dir takes place on the current directory.
FOR /F "tokens=1-5 delims=/-: " %%a IN ("%%~ts") DO (
should work for you if you can use last-update-date in place of create-date.
So - if %%c is not empty, set the new name to (the name part of the file in %%s)+space+the date string+(the extension in %%s)
And then do the xcopy - using the old name unless it was modified.

Rename multiple files in a directory using batch script

I have about 1000 images and they have name like "IMG-12223". I want to rename them to 1 2 3 4 ... 1000. How can I do that. I have written a batch script which list the files but I don't know how to rename each file. e.g. rename first image with name "IMG-12223" to 1 , second image with name "IMG-23441" to 2 and so on ...
for /r %%i in (*) do (
echo %c%
)
Here's the script. Just put the script in your folder and run it.
#echo off & setlocal EnableDelayedExpansion
set a=1
for /f "delims=" %%i in ('dir /b *') do (
if not "%%~nxi"=="%~nx0" (
ren "%%i" "!a!"
set /a a+=1
)
)
If you want to keep the extensions, i.e. rename "IMG-12223.jpg", "IMG-12224.jpg", etc to "1.jpg", "2.jpg", etc, you may use the following script.
#echo off & setlocal EnableDelayedExpansion
set a=1
for /f "delims=" %%i in ('dir /b *.jpg') do (
ren "%%i" "!a!.jpg"
set /a a+=1
)
[Update] Here're explanations for the lines mentioned in Jack's comment.
setlocal EnableDelayedExpansion
In general, we want the variable a to be delayed expansion when it's executed but not the line is read. Without it, the variable a cannot get its increased value but always 1.
For the detail of EnableDelayedExpansion, please refer to the answer https://stackoverflow.com/a/18464353/2749114.
for /f "delims=" %%i in ('dir /b *.jpg')
Here dir with /b option, lists only file names of all jpg files.
The for loop traverses and renames all jpg files.
For the delims option, since the default delimiter character is a space, without the option delims=, it fails with the image files with spaces in the file names. I.E. for an image file named "img with spaces.jpg", without the option, the value of %%i is "img" but not the whole name "img with spaces.jpg", which is incorrect.
For for loop, please refer to the page http://ss64.com/nt/for_f.html.
if not "%%~ni"=="%~n0"
I have change it to if not "%%~nxi"=="%~nx0" to be more accurate. And the codes attached have been updated.
It's actually used to avoid to rename the bat file itself. If we limit the renaming only upon "jpg" files, then the line is not needed.
%%~nxi is the file name with extension for each file traversed. And %~nx0 is the running bat file with extension. For details, please refer to the page DOS BAT file equivalent to Unix basename command?.
There is no need for a batch script. A simple one liner from the command line can do the job :-)
I use DIR /B to generate the list of files, piped to FINDSTR to number the files, all enclosed withn FOR /F to parse the result and perform the rename.
for /f "delims=: tokens=1*" %A in ('dir /b *.jpg^|findstr /n "^"') do #ren "%B" "%A%~xB"
Double the percents if you want to put the command in a batch script.
Try this, you have pair of namevalues in a text file then loop values and do the magic. Namevalues are separated by empty spaces. This allows you to map old->new filenames accordingly. Or you keep idx+1 counter and use it for new filenames.
keyvalue.bat
#echo off
set idx=0
for /F "tokens=1,2" %%A in (keyvalue.txt) do call :PROCESS "%%A" "%%B"
GOTO :END
:PROCESS
set var1=%~1
set var2=%~2
set /A idx=%idx%+1
echo %var1% goes to %var2% (%idx%)
GOTO :EOF
:END
pause
keyvalue.txt
file888.dat newfile1.dat
file333.dat newfile2.dat
file9.dat newfile3.dat
file01.dat newfile4.dat

Batch: Rename multiple files using input string

I am trying to rename files after the user inputs a string they want to remove from the file name. This works fine except when I want to rename files that are in a different location than the script:
Here is what i have so far which works if I dont specific the file path (e.g. remove C:\DATABASE\*.* /s)
SET /P X=Type in the String that you want to remove and then press ENTER:
set deletestring=%X%
for /f "delims==" %%F in ('dir C:\DATABASE\*.* /s /b ^| find "%deletestring%"') do (
set oldfilename=%%F
set newfilename=!oldfilename:%deletestring%=!
Ren "!oldfilename!" "!newfilename!"
)
Thanks!
Use this instead. e.g.:
remove *.*
or
remove "relative path\*.*"
or
remove C:\DATABASE\*.*
or
remove "C:\My Database\2010-*.bak"
Meaning that a directory and file mask must be specified. Here's the remove.bat file:
#echo off
setlocal enabledelayedexpansion
set mask=%~1
set mask=!mask:%~dp1=!
if not exist "%~1" (
echo No files found
goto :eof
)
pushd "%~dp1"
SET /P X=Type in the String that you want to remove and then press ENTER:
set deletestring=%X%
for /f "delims==" %%F in ('dir "%mask%" /s /b ^| find "%deletestring%"') do (
set oldfilename=%%F
set newfilename=!oldfilename:%deletestring%=!
Ren "!oldfilename!" "!newfilename!"
)
Your primary problem you are running into is that the 1st argument to REN can accept full path info, but the 2nd can only contain the new name without path info. You can use the ~nx modifier to extract the name and extension from the full path reported by the FOR /F command.
Your FOR /F options are not reliable - it will break if the file name contains =. You want to set delims to nothing instead.
This problem is actually more complicated than it first looks. Your code will attempt to rename both files and directories. If you want to rename the directories then you must rename in reverse alpha order because the entire list is built before any thing is renamed. If you process in normal alpha order and rename a directory, then subsequent entries within that directory will not be found.
The FIND filter in the IN() clause is not necessary. Ideally your filter should only match the file or directory name, not the path. That is doable, but a bit tricky. I would simply skip the filtering in the IN() clause and do it in the DO clause.
A file or directory name can contain ! character. But the FOR variable expansion will be corrupted if it contains ! and delayed expansion is enabled. The problem can be avoided by toggling delayed expansion on and off within the loop.
It is possible for the entire name to be removed by the search and replace, but you cannot rename a file to nothing. So I added a test to ensure there is a name left.
setlocal disableDelayedExpansion
SET /P "X=Type in the String that you want to remove and then press ENTER:"
for /f "delims=" %%F in ('dir C:\DATABASE\* /s /b ^| sort /r') do (
set "old=%%F"
set "file=%%~nxF"
setlocal enableDelayedExpansion
set "new=!file:%X%=!"
if defined new if !new! neq !file! ren "!old!" "!new!"
endlocal
)
If you don't really want to rename directories then you need to add the /A-D option. I first thought you could use a FOR /R statement, but that could potentially cause the same file to be renamed twice. FOR /F buffers the entire result set before processing any files, but FOR /R does not.
setlocal disableDelayedExpansion
SET /P "X=Type in the String that you want to remove and then press ENTER:"
for /f "delims=" %%F in ('dir C:\DATABASE\* /s /b /a-d') do (
set "old=%%F"
set "file=%%~nxF"
setlocal enableDelayedExpansion
set "new=!file:%X%=!"
if defined new if !new! neq !file! ren "!old!" "!new!"
endlocal
)

Resources