I have a list of en.srt files in my folder. I need to convert them to .srt extension.
For example
Criminal Minds - 1x01 - Extreme Aggressor.en.srt to Criminal Minds - 1x01 - Extreme Aggressor.srt
Tried the below command and it didn't work,
ren *.en.srt *.srt
Renaming extension like ren *.srt *.srv works. (Changing all files' extensions in a folder with one command on Windows)
Would like to know if there is a workaround for this?
A simply though clumsy method is to rename the files twice – first remove .srt, then change .en to .srt (given that there are no other files *.en):
ren "*.en.srt" "*." & ren "*.en" "*.srt"
A more elegant solution is the one provided by user Mofi in his comment:
#for /F "eol=| delims=" %I in ('dir "*.en.srt" /B /A:-D 2^> nul') do #for %J in ("%~nI") do #ren "%~I" "%~nJ%~xI"
In a batch-file this code would look similar to this (note the necessarily doubled %-signs):
#echo off
rem // Loop through all matching files:
for /F "eol=| delims=" %%I in ('dir "*.en.srt" /B /A:-D 2^> nul') do (
rem /* There are `~`-modifiers for `for` meta-variables that allow to split file names:
rem `~n` returns the base name, so the (last) extension becomes removed;
rem `~x` returns the extension (including the leading `.`);
rem therefore, `%%~nI` is the original file name with `.srt` removed, hence
rem ending with `.en`, and `%%~xI` is the original extension `.srt`;
rem another loop is used to also split off `.en` from `%%~nI`: */
for %%J in ("%%~nI") do (
rem /* Now `%%~J` returned the same as `%%~nI`, but `%%~nJ` removes `.en`;
rem so finally, rename the file to `%%~nJ` plus the original extension `.srt`: */
ren "%%~I" "%%~nJ%%~xI"
)
)
Following the thorough thread How does the Windows RENAME command interpret wildcards? on Super User, I found out that there is a way using a single ren command:
ren "*.en.srt" "?????????????????????????????????????????.srt"
However, you need to make sure to have enough ?, namely as many as there are characters in longest matching file name without .en.srt; otherwise, file names become truncated. You can avoid truncation by replacing the same sequence of ? instead of *, so longer file names are not renamed at all:
ren "?????????????????????????????????????????.en.srt" "?????????????????????????????????????????.srt"
Anyway, this only works when the original file names do not contain any more . besides the two in .en.srt; otherwise, everything behind the first . becomes removed and (finally replaced by srt).
Not difficult in PowerShell to identify the files and replace the end of the filename with a regex. When you are confident that the files will be renamed correctly, remove the -WhatIf from the Move-Item command.
powershell -NoLogo -NoProfile -Command ^
"Get-ChildItem -File -Path '.' -Filter '*.en.srt' |" ^
"ForEach-Object {" ^
"Move-Item -Path $_.FullName -Destination $($_.FullName -replace 'en.srt$','srt') -WhatIf" ^
"}"
Of course, it would be easier if the command shell were PowerShell. BTW, this exact same code would work on Linux and Mac without change.
Get-ChildItem -File -Path '.' -Filter '*.en.srt' |
ForEach-Object {
Move-Item -Path $_.FullName -Destination $($_.FullName -replace 'en.srt$','srt') -WhatIf
}
I don't have a cmd at my disposition but I would guess that
ren *.en.srt *.tmp
ren *.tmp *.srt
works
Related
I want to remove first 21 characters from every ".pdf" file in folder.
My command:
rename "*.pdf" "/////////////////////*.pdf"
The problem remains only the following: The first file is renamed twice. Deletes the first 42 characters. Other files are renamen correctly (21).
This command would do it, but there are many undetected pitfalls. What if the filename does not have more than 21 characters? What if the NewName duplicates an existing filename?
powershell -NoLogo -NoProfile -Command ^
"Get-ChildItem .\*.pdf |" ^
"ForEach-Object { Rename-Item -Path $_.FullName -NewName $($_.Name[21..($_.Name.Length)] -join '') -WhatIf }"
The problem is, that the file mask *.pdf may be "updated" with newly created files during the process.
The same goes for a simple for %%a in (*.pdf) loop.
To work around this, make sure, the list of files gets generated before rename does it's thing:
for /f "delims=" %%a in ('dir /b *.pdf') do rename "%%a" "/////////////////////*.pdf"
The do part is only executed, after the (...) part is done, so newly created/changed files won't be processed a second time.
Same pitfalls as in lit's answer apply:
What if the filename does not have more than 21 characters?
What if the NewName duplicates an existing filename?
I have several files like:
a.txt
a$.txt
a$b.txt
b.txt
b$.txt
b$c.txt
I would like to print file whose name does not contain '$' using Windows command line for file name pattern matching like regular expression:
for %%f in ([^$]+.txt) do type %%f
or
for %%f in ([a-zA-Z]+.txt) do type %%f
But it does not work. How can I do this using Windows command line? Thanks!
The for loop, like almost all cmd commands, does not support something like regular expressions. The only command that supports a tiny excerpt of those is findstr, which can be used together with dir to get the desired result:
#echo off
for /F "delims= eol=|" %%f in ('
dir /B /A:-D "*.txt" ^| findstr "^[^$][^$]*\.txt$"
') do (
>&2 echo/%%f
type "%%f"
)
This could even be simplified by replacing the portion findstr "^[^$][^$]*\.txt$" with find/V "$".
As 'Windows command line' includes powershell.exe as well as cmd.exe, I thought I'd offer a powershell based idea too.
Directly in powershell:
Get-Content -Path 'C:\Users\Xiagao\Desktop\*.txt' -Exclude '*$*.txt'
In cmd/batch-file, but leveraging powershell:
PowerShell -NoP "GC 'C:\Users\Xiagao\Desktop\*.txt' -Ex '*$*.txt'"
You would obviously modify the path to your source files location, (use .\*.txt for the current directory).
I'm trying to list out file names excluding their extension,
How I want it:
File1
File2
File3
How it currently is:
File1.txt
File2.txt
File3.txt
I tried using
#echo off
dir /A:-D /B
pause
but it isn't working. I tried it in both a batch file and in command prompt.
Am I using the right command?
Use FOR and ECHO to achieve this
For example, assuming the extension is always .txt:
for %f in ("*.txt") do #echo %~nf
Instead of using DIR, we are using the FOR command to go through the list and sending each one to ECHO, with the "~n" option inserted into the %f, to cause the extension to be not shown.
An alternative is
FORFILES /c "cmd /c echo #fname"
However with this I get quotation marks around each output filename, which isn't what you want.
If running inside a batch file, you need to double the %'s for variables
for %%f in ("*.txt") do #echo %%~nf
If you need to handle multiple file extensions
As long the directory doesn't contain any subdirectories whose names have an extension, you can generalise the *.txt to *.*:
for %f in ("*.*") do #echo %~nf
If you may have some filenames with only an extension
Where the file has an extension but nothing before it, e.g. .gitignore, the resulting empty ECHO command will output an inane message, such as ECHO is on. To avoid this ruining your onward plans, you can filter out lines containing ECHO is, with the FIND command and the /V option:
for %f in ("*.*") do #echo %~nf | find /v "ECHO is"
If your local language causes DOS to output something other than ECHO is then this filtering will not work. And it will miss any file that happens to contain ECHO is in the filename.
To search subdirectories too, add '/R' to the 'for'
for /R %f in ("*.png") do #echo %~nf | find /v "ECHO is"
Conclusion
This is all crazy, of course, but this is the agonising price we pay for using Batch language instead of an actual sensible language. I am like an alcoholic, promising to all and sundry that I will never write a line of Batch code again, and then finding myself coming back to do so again, sheepishly.
It'll be much easier in PowerShell
(Get-ChildItem -File).BaseName
or
Get-ChildItem | ForEach-Object { $_.BaseName }
Get-ChildItem can be replaced with the aliases ls, gci or dir and ForEach-Object can be replaced with %
So from cmd you can run either of these to achieve the purpose
powershell -Com "(ls -File).BaseName"
powershell -C (ls^ -File).BaseName
powershell (ls^ -af).BaseName
To add to Eureka's answer, the vanilla dir command cannot achieve what you're looking for.
C:\Users\jacob>dir /?
Displays a list of files and subdirectories in a directory.
DIR [drive:][path][filename] [/A[[:]attributes]] [/B] [/C] [/D] [/L] [/N]
[/O[[:]sortorder]] [/P] [/Q] [/R] [/S] [/T[[:]timefield]] [/W] [/X] [/4]
[drive:][path][filename]
Specifies drive, directory, and/or files to list.
/A Displays files with specified attributes.
attributes D Directories R Read-only files
H Hidden files A Files ready for archiving
S System files I Not content indexed files
L Reparse Points - Prefix meaning not
/B Uses bare format (no heading information or summary).
/C Display the thousand separator in file sizes. This is the
default. Use /-C to disable display of separator.
/D Same as wide but files are list sorted by column.
/L Uses lowercase.
/N New long list format where filenames are on the far right.
/O List by files in sorted order.
sortorder N By name (alphabetic) S By size (smallest first)
E By extension (alphabetic) D By date/time (oldest first)
G Group directories first - Prefix to reverse order
/P Pauses after each screenful of information.
/Q Display the owner of the file.
/R Display alternate data streams of the file.
/S Displays files in specified directory and all subdirectories.
/T Controls which time field displayed or used for sorting
timefield C Creation
A Last Access
W Last Written
/W Uses wide list format.
/X This displays the short names generated for non-8dot3 file
names. The format is that of /N with the short name inserted
before the long name. If no short name is present, blanks are
displayed in its place.
/4 Displays four-digit years
Switches may be preset in the DIRCMD environment variable. Override
preset switches by prefixing any switch with - (hyphen)--for example, /-W.
Additionally, as an alternative to the suggestion to use ("*.txt"), if your file list includes multiple extensions you might either exclude different extensions or use *.* to get all files with a . in the name. Play around with that glob to get what you want out of it.
This is possible with a dir command and a for loop:
#echo off
for /F "delims= eol=" %%A IN ('dir /A-D /B') do echo %%~nA
If you want the full path without the extension, try:
#echo off
for /F "delims= eol=" %%A IN ('dir /A-D /B') do echo %%~dpnA
For cmd one-line:
for /F "delims= eol=" %A IN ('dir /A-D /B') do echo %~nA
And for the full path without the extension, try:
for /F "delims= eol=" %A IN ('dir /A-D /B') do echo %~dpnA
These small programs, loop through all the files in the folder except directories, and echo only the filenames/full paths without the extension.
dir -Name -File
This is for PowerShell
I have some files as listed below and I want to use a batch script to rename these files by removing a number and a fixed string from begin and keep just number before file extension.
Original name New name
---------------- --------
1_Asset_28.png -> 28.png
212_Asset_2.png -> 2.png
1_Asset_288.png -> 288.png
89_Asset_117.png -> 117.png
The goal is to delete first number and _Asset_.
I have been searching for a while, but still don't know how to do this.
How can this file renaming task be done with a batch file?
Heres one option for you:
#Echo Off
For %%A In ("*_Asset_*.png") Do (Set "fN=%%A"
Call Ren "%%A" "%%fN:*_Asset_=%%")
You can split the input by the underscore and use the last token.
When you cannot use PowerShell you can use the for /f tokenizer, like this:
set input=1_Asset_28.png
rem split by underscore
for /f "tokens=3 delims=_" %%a in ("%input%") do set "output=%%a"
echo output %output%"
will print
output "28.png"
Try this PowerShell command:
Get-ChildItem -Filter *Asset*.png | %{ Rename-Item $_.FullName -NewName $_.FullName.Substring($_.FullName.LastIndexOf('_') + 1) }
I got difficulties in replacing multiple file names.
The scenario would be :
[Before]
C:¥data¥
-HOSTNAME1_20170921_5555.zip
-HOSTNAME2_20170921_5555.zip
-HOSTNAME3_20170921_5555.zip
[After]
C:¥data¥
-HOSTNAME1_20170908_5555.zip
-HOSTNAME2_20170908_5555.zip
-HOSTNAME3_20170908_5555.zip
I tried the below command but not getting satisfied result.
RENAME C:¥data¥*20170921_5555.zip *20170908_5555.zip
Unfortunately the result was:
C:¥data¥
-HOSTNAME1_20170920170908_5555.zip
-HOSTNAME2_20170920170908_5555.zip
-HOSTNAME3_20170920170908_5555.zip
Anyone can solve the problem?
and tell me why the above code was not working as expected.
You specifically require a single line, so here is a powershell version.
get-childitem *20170921_5555.zip | foreach { rename-item $_ $_.Name.Replace("20170921_5555", "20170908_5555") }
Use a for to iterate the files with the wrong date
a 2nd stacked for /f to split the name at the _ and
rename replacing the 2nd element with the proper date
With one single cmd line:
> #for %A in (*_20170921_*.zip) do #for /f "tokens=1,2* delims=_" %B in ("%A") do #echo ren "%A" "%B_20170908_%D"
ren "¥data¥-HOSTNAME1_20170921_5555.zip" "¥data¥-HOSTNAME1_20170908_5555.zip"
ren "¥data¥-HOSTNAME2_20170921_5555.zip" "¥data¥-HOSTNAME2_20170908_5555.zip"
ren "¥data¥-HOSTNAME3_20170921_5555.zip" "¥data¥-HOSTNAME3_20170908_5555.zip"
If the output looks OK remove the echo in front of the ren command.
If used in a batch file the percent signs have to be doubled %%
BTW you could also use this Powershell script from batch:
powershell -NoP -C "gci '*_20170921_*.zip'|rni -NewName {$_.Name -replace '_20170921_','_20170908_'} -WhatIf
If the output looks OK, remove the trailing -WhatIf