Another regex-in-RENAME question

May 23, 2010
[D:\TMP] dir /b /a-d *-*
If I want to convert all those dashes to underscores in the filenames, I can use this command: ren ::- ::_ But what if I want to convert the dashes to spaces?

I haven't figured out how to include a space character that is recognized as other than an empty string (or, literally. the characters I've typed in). I've tried space, quoted space, \x20, \040, \o{40}.

I'm using Perl REs.

Hmm. I did find a way to do it. Pretty dorky. If you know a better solution, let me know.
[D:\TMP] ren ::- ":: StringNotInAnyFileName"
[D:\TMP] ren ::StringNotInAnyFileName ::
Just for completeness: suppose I want to go back the other way: replace the spaces with dashes. The best way I've found to do that is this:
do until errorlevel gt 0 (ren ":: (.)" ::-\1)
...with one caveat: if a filename that originally ended with dashes had those dashes converted to spaces (as per the previous post), then converted back to dashes using the code here, there would be no trailing dashes, as trailing spaces in a filename appear not to be preserved.
ren ::- ::_
I'm a bit surprised that that works. I don't think I have ever used REN with regular expressions. I would have (naively) thought that the first RE specify the files you want to operate on. Apparently, that will change '-' to '_' in EVERY file name! That's a little scary.
ren "*-*" "%%@replace[-, ,*]"
Is '*' in the destination guaranteed to mean the whole file name? The help says this (below); I'm not sure what it means.

Note: The wildcard expansion process will attempt to allow both CMD-style "extension" matching (assumes only one extension, at the end of the word) and the advanced TCC string matching (allowing things like *.*.abc) when an asterisk is encountered in the destination of a REN command.
This proves nothing but in the example below (apparently) the first '*' in the destination became the whole file name and the others became empty strings.

v:\> ren /n *-*--*.txt *_*_*.txt
V:\a-b--c.txt -> V:\a-b--c.txt__.txt
     1 file would be renamed
This is a bit contrived, but it does put spaces in there (though not two spaces where there were two '-'s).

v:\> ren /n "::([^-]+)[-]+([^-]+)[-]+([^-]*)" "::\1 \2 \3"
V:\a-b--c.txt -> V:\a b c.txt
     1 file would be renamed
I would have (naively) thought that the first RE specify the files you want to operate on. Apparently, that will change '-' to '_' in EVERY file name! That's a little scary.
Well, it does specify the files you want to operate on: every file whose name contains a dash. The RE is both file-selection and pattern-to-replace. If I wanted to be more specific, I could use ^ and $ anchors (or even just a little more of the name) and come up with a pattern that would include the set of files I want to operate against. And then be sure to include back-references in the second RE to include what was included in the first one.
Yes. But I just don't (didn't) think of REN and pattern replacement together. The source regex matching the whole file name seems safer.
I like REs: they can be very precise in selecting the fileset I want to operate on and what I want to do to it. But they can also be a PITA, especially when it comes to greedy/non-greedy, escape characters, and the apparent inability to match hex/octal patterns (see first post). They require thorough testing before I ever include them in a batch file, and never a run from the command line without first using the /n option.

Vince, not only is ren /n "::([^-]+)[-]+([^-]+)[-]+([^-]*)" "::\1 \2 \3" contrived: it requires documentation!

The ren "*-*" "%%@replace[-, ,*]" is a good non-RE way to do it.

Thanks, everyone, for your input.

Similar threads