Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Windows ren command to remove ! from filename

Tags:

batch-file

cmd

I have a bunch of files that are in the following format

filename-!#.ext

where # is an incrementing number to prevent collisions. I would like to just remove the ! from the filename so it reads as

filename-#.ext

It seems like I could do this with the ren command and wildcards but having a hard time getting it to work. I tried running this:

ren *!?.ext *?.ext

My thought is the * should match the filename- part, then !, then the ? for the numeric. However, the resulting file is named this:

filename-!#.ext.ext

and I can't quite figure out why.

The filename part can be dynamic, but won't contain any !'s. Any ideas?

like image 610
user3334986 Avatar asked Aug 15 '18 15:08

user3334986


3 Answers

I think you'll have to resort to a small batch file for this:

@echo off
    setlocal
    for %%a in (*!*.ext) do call :remove "%%~a"
    goto :eof

:remove
    set "FROM=%~1"
    set "TO=%FROM:!=%"
    ren "%FROM%" "%TO%"
    goto :eof

The above will – for all files containing an exclamation mark and extension ext – call the remove function. This takes the original name (FROM) and determines the new name (TO) by using the %var:find=replace% syntax to remove any exclamation mark (replaces it with an empty string).

Notes

  • You cannot use find/replace with either %%a or %0 type variables, so you have to assign it to a named variable first.

  • I originally tried doing this "inline" with the for statement (e.g. for ... ( ending )) but to do that, you would have to enable delayed-expansion (because you would need to access a named variable in a loop). However, delayed-expansion uses ! (instead of %) to reference variables and this got in the way of the ! we were trying to remove. There may be a way of doing this, but I haven't found it. Using call will be slightly slower, but not significantly unless you've got thousands of files.

  • You don't really need to create TO (you could perform the replacement on the ren command-line) but I used it for clarity.

  • This will work for all files with an exclamation mark: it doesn't check the bit after is numeric.

like image 64
TripeHound Avatar answered Oct 18 '22 02:10

TripeHound


I think it is not a good idea to let rename select the files, but instead do it with a for-loop and then execute the rename for every file:

for %%F in (*!*) do (
    set "nxF=%%~nxF"
    call ren "%%nxF%%" "%%nxF:!=%%"
)

You really have to use call here instead of delayedExpansion, because delayedExpansion would destroy the rename-arguments (because they contain !)

like image 35
timlg07 Avatar answered Oct 18 '22 03:10

timlg07


Based upon your provided information and just for the sake of offering something a little different, you could let delayed expansion do the work for you, (as it will remove the unwanted exclamation mark for you).!

@For %%A In ("*-!?.ext") Do @Set "_=%%A" & SetLocal EnableDelayedExpansion & Ren "!_!" "%%A" & EndLocal

You could probably also do it with a nested for loop:

@For %%A In ("*-!?.ext") Do @For /F "Tokens=1*Delims=!" %%B In ("%%A") Do @Ren "%%A" "%%B%%C"

…and from the Command Prompt:

For %A In ("*-!?.ext") Do @For /F "Tokens=1*Delims=!" %B In ("%A") Do @Ren "%A" "%B%C"
like image 41
Compo Avatar answered Oct 18 '22 03:10

Compo