4

I have a bunch of files that look like this:

A.File.With.Dots.Instead.Of.Spaces.Extension

Which I want to transform via a regex into:

A File With Dots Instead Of Spaces.Extension

It has to be in one regex (because I want to use it with Total Commander's batch rename tool).

Help me, regex gurus, you're my only hope.

Edit

Several people suggested two-step solutions. Two steps really make this problem trivial, and I was really hoping to find a one-step solution that would work in TC. I did, BTW, manage to find a one-step solution that works as long as there's an even number of dots in the file name. So I'm still hoping for a silver bullet expression (or a proof/explanation of why one is strictly impossible).

alexn
  • 57,867
  • 14
  • 111
  • 145
Assaf Lavie
  • 73,079
  • 34
  • 148
  • 203

6 Answers6

4

It appears Total Commander's regex library does not support lookaround expressions, so you're probably going to have to replace a number of dots at a time, until there are no dots left. Replace:

([^.]*)\.([^.]*)\.([^.]*)\.([^.]*)$

with

$1 $2 $3.$4

(Repeat the sequence and the number of backreferences for more efficiency. You can go up to $9, which may or may not be enough.)

It doesn't appear there is any way to do it with a single, definitive expression in Total Commander, sorry.

molf
  • 73,644
  • 13
  • 135
  • 118
  • 1
    There's no need to escape dots within character classes: ([^.]*)\.([^.]*)\.([^.]*)\.([^.]*)$ – Helen Jun 20 '09 at 14:50
2

Basically:

/\.(?=.*?\.)//

will do it in pure regex terms. This means, replace any period that is followed by a string of characters (non-greedy) and then a period with nothing. This is a positive lookahead.

In PHP this is done as:

$output = preg_replace('/\.(?=.*?\.)/', '', $input);

Other languages vary but the principle is the same.

cletus
  • 616,129
  • 168
  • 910
  • 942
  • I don't think the ? after the .* is necessary... it will just backtrack anyway. *some* regex engines *might* be able to optimize it a little better, but [^.]* instead would work optimally even for a really unoptimized regex engine. – ʞɔıu Jun 20 '09 at 14:35
  • Generally speaking you probably want to avoid backtracking if you can. – cletus Jun 20 '09 at 14:39
  • most regex engines will backtrack regardless of the ? being there or not, it's just a matter of how far they will backtrack. – ʞɔıu Jun 20 '09 at 14:53
1

Here's one based on your almost-solution:

/\.([^.]*(\.[^.]+$)?)/\1/

This is, roughly, "any dot stuff, minus the dot, and maybe plus another dot stuff at the end of the line." I couldn't quite tell if you wanted the dots removed or turned to spaces - if the latter, change the substitution to " \1" (minus the quotes, of course).

[Edited to change the + to a *, as Helen's below.]

John Hyland
  • 6,855
  • 28
  • 32
1

Another pattern to find all dots but the last in a (windows) filename that I've found works for me in Mass File Renamer is:

(?!\.\w*$)\.

I don't know how useful that is to other users, but this page was an early search result and if that had been on here it would have saved me some time.

It excludes the result if it's followed by an uninterrupted sequence of alphanumeric characters leading to the end of the input (filename) but otherwise finds all instances of the dot character.

Leon
  • 11
  • 1
1

Or substitute all dots with space, then substitute [space][Extension] with .[Extension]

A.File.With.Dots.Instead.Of.Spaces.Extension to A File With Dots Instead Of Spaces Extension to A File With Dots Instead Of Spaces.Extension

bop
  • 11
  • 1
0

You can do that with Lookahead. However I don't know which kind of regex support you have.

/\.(?=.*\.)//

Which roughly translates to Any dot /\./ that has something and a dot afterwards. Obviously the last dot is the only one not complying. I leave out the "optionality" of something between dots, because the data looks like something will always be in between and the "optionality" has a performance cost.

Check: http://www.regular-expressions.info/lookaround.html

eipipuz
  • 563
  • 1
  • 7
  • 16