Thursday, October 29, 2015

windows - Add leading zeros to the middle of non-sequential filenames


I've got over 1200 files (inside subfolders) which I have to rename by adding leading zeros to the middle of the file name. I want to do this because the program I load them into doesn't know that "10" comes after "2".


Here is an example of what I have:



  • Roses MIDI 1 - C Maj.mid

  • Roses MIDI 1 - Var1.mid

  • Phantom MIDI Loop 26 - C Min.mid

  • Galaxy Chord MIDI 231 - A Min.mid

  • Posty MIDI Loop 1 - 100 BPM E Maj.mid


And here is what I would like it to be:



  • Roses MIDI 001 - C Maj.mid

  • Roses MIDI 001 - Var1.mid

  • Phantom MIDI Loop 026 - C Min.mid

  • Galaxy Chord MIDI 231 - A Min.mid

  • Posty MIDI Loop 009 - 160 BPM G# Min.mid


I had a little success with the following powershell command:


get-childitem *.mid -recurse | foreach { rename-item $_ $_.Name.Replace("MIDI 1 ", "MIDI 001 ")}

This added 2 zeros to the front of every "1" which followed a "MIDI" and had a space behind it. I could do this for all the single digit ones I want to rename, but it breaks down when you get to the 10s, 20s, etc.


Is there a command (or a free program) which could do this automatically for me? It feels like there should be... but, this is my first look into powershell, so I'm not sure what all it can do, and what limitations it has.


Also, if it helps (I just checked) the number I want to prepend zeros onto is always the first number in the file name.


Answer



So.. looks like I took to powershell faster than I thought I would.
After many hours, a headache, and 20+ google tabs, here is the answer I crafted:


get-childitem *.mid -recurse | foreach {
$tmp = $_.Name
$tmp = $tmp -split ' ';
$noNum = $true;
$tmp = foreach ($s in $tmp) {
if($noNum){
if($s -match "\b\d\b"){"00$s"; $noNum = $false}
elseif($s -match "\b\d\d\b"){"0$s"; $noNum = $false}
else{$s}
}
else {$s}
}
$tmp = $tmp -join ' ';
rename-item $_ $tmp;
}

and a translation:


get all midi files (including those in a subfolders) and loop through them.
Create a temp var, and store the name of the midi file in it (no directory)
Split temp at each ' '
create noNum var and set it to false (this keeps track of if we've hit a number)
loop through each substring in tmp, changing them as needed
if we have not found the first number, check for it
if the substring is a 1 digit num, add two 0s, and set noNum to false
if the substring is a 2 digit num, add one 0, and set noNum to false
else, not a number, just return substring
else, first number found, just return substring
join tmp substrings back together with a ' ' in between each one
rename the file to tmp.

I'm sure there is a more elegant solution (which I'd love to see!) but this worked for me =]




P.S.
If anyone else got midi files from Cymatics, you may want to run the following to get rid of their prefix:


get-childitem *.mid -recurse | foreach { rename-item $_ $_.Name.Replace("Cymatics - ", "")}

then/or


get-childitem *.mid -recurse | foreach { rename-item $_ $_.Name.Replace("Cymatics ", "")}

In the program I am using, having the prefix makes it waaaay to long to see the number.. so removing the prefix is a must.


No comments:

Post a Comment

linux - How to SSH to ec2 instance in VPC private subnet via NAT server

I have created a VPC in aws with a public subnet and a private subnet. The private subnet does not have direct access to external network. S...