16

I have 14,000 pictures sorted into files by year and month but taken with multiple cameras and I want the file name to reflect the date taken. For example October 16, 1998 pictures are in a folder called 1998\10 October\19981016.

I want the all the pictures to be named 19981016_0001 19981016_0002 etc. I tried multiple suggestions but it hasn't worked.

I can get to the point where it lists the folder I want to change but I'm unable to actually change it. All of my pictures are .jpg.

Attempts I created a temp file of copies in case I messed it up. I started by typing cd "C:\Documents and Settings\Brooke LastName\Desktop\Temp" then after successfully getting my file to load I used a formula I found on this forum.

ls *jpg | Foreach {$i=1} {Rename-Item _ -NewName ("$($.19981016){0:00000000#} .jpg" -f $i++) -whatif}

The error I got said

Unexpected token ' .19981016' in expression or statement.

At line:1 char:12 + $.19981016 <<<<

The error repeated several times.

I found several formulas on the web but most created files that would number with parentheses for example vacation (1).jpg. I want a four digit counter after an underscore at the end of my date, e.g. 19981016_0001

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
Brooke
  • 163
  • 1
  • 1
  • 5

3 Answers3

56

The syntax is way off. A few issues:

  • I'm not sure what $($.19981016) was intended to produce, but $( ) evaluates the expression in the parentheses and interpolates the result into the string, and you're getting the error because $.19981016is not a valid expression. The error would be repeated for each .jpg file in the directory.
  • {0:00000000#} in a formatted string will create a zero-padded number of 9 digits, but a shorter way to do that is {0:D9}. However, I thought you wanted the zero-padded number to have 4 digits, so that should be {0:0000#} or {0:D4}.
  • I'm not sure what Foreach {$i=1} { [...] is supposed to do. The keyword foreach can mean a foreach loop, or it can be shorthand for Foreach-Object. In this context, receiving input from a pipeline, it's necessarily the latter, but this syntax is incorrect either way.

This will do what you want, if I understand the description correctly:

$i = 1
Get-ChildItem *.jpg | %{Rename-Item $_ -NewName ('19981016_{0:D4}.jpg' -f $i++)}

The filenames will be 19981016_0001.jpg, 19981016_0002.jpg, 19981016_0003.jpg, etc.

A few notes:

  • You said that you want filenames like 19981016_0001, but I'm assuming you want to keep the .jpg extension.
  • You need to initialize $i, otherwise it will start from 0 if it's not yet defined, or worse yet, from some other number if $i was used previously in the same PowerShell session. For example, if you have 1,432 .jpg files in the directory, and you run the command first with -WhatIf, and then run it for real, the numbers will start from 1432.
  • $i++ increments $i by 1. However, if you're using it as a value, it increments after the value is read; that's why if $i is undefined, it will start from 0.
  • Get-ChildItem is the same as ls. I used the native PowerShell name, but they're interchangeable (ls, dir, and gci are all aliases for Get-ChildItem).
  • %{ } is shorthand for Foreach-Object
Adi Inbar
  • 12,097
  • 13
  • 56
  • 69
  • 1
    Very usefull ! Thank you for details .. Where the complete documentation can be found ? :/ I was not able to find accurate article but this thread, thank you ! – Stphane Sep 24 '14 at 09:45
  • @f00bar Documentation for what aspect? This answer covers several topics. If you mean documentation for bulk file renaming, there isn't any because it's not really a discrete topic, other than the basic idea of feeding the filenames to a loop using **Rename-Item**. Documentation for how to create the new name would be specific to whatever it is you want to do. Case in point, most bulk renaming would be done with regex replacements, which aren't even involved here. In that case the topic you'd be looking for documentation about would be regex replacements, not bulk file renaming. – Adi Inbar Sep 24 '14 at 21:05
  • ...If you want to know about string formatting, the official term is "composite format string", and [the full documentation can be found at MSDN](http://msdn.microsoft.com/en-us/library/txafckwd%28v=vs.110%29.aspx), but you can get more concise and intuitive documentation by googling ".net format strings" or "powershell format strings" or "powershell -f operator". – Adi Inbar Sep 24 '14 at 21:07
  • @AdiInbar Thank you `:)`, I had trouble trying to find details about looping over directory's files listing and string replacement formatting. – Stphane Sep 25 '14 at 07:55
  • I have a similar case, and I would like to know how can generate a sequence only with odd numbers, like this e.g `19981016_0001.jpg, 19981016_0003.jpg, 19981016_0005.jpg,... `? it is because I have a scanned document with the odd pages in one directory and the even pages in other one. – Darwin PC Nov 16 '15 at 00:27
  • I always had the windows `.bat ren` in my back pocket, but there were so many nuanced steps that made the manual process more appealing. This method is so much easier and useful. Thank you – Alexander Dixon Apr 03 '18 at 20:18
  • Nicely done; re `Foreach {$i=1} { [...]`: aside from the missing closing `}`, the syntax is correct : the first script block binds to the `-Begin` parameter and is used for initialization before processing of pipeline input begins. – mklement0 Jul 18 '18 at 15:50
  • I tried this on a sequence of 25000 files and it numbered them in random order. Is there a way to ensure it maintains regular alphabetical order? – Elliott B Aug 04 '22 at 20:32
1

This comes close to the original question. You can actually pass a script block array to foreach-object -process, as documented (barely). I only know this after Bruce Payette's book. The containing folder name is "19981016". The source filenames may not go in the order you expect.

ls *jpg | 
Foreach {$i=1} {Rename-Item $_ -NewName ("$($_.directory.name)_{0:000#}.jpg" -f
  $i++) -whatif}


What if: Performing the operation "Rename File" on target "Item: C:\users\js\19981016\file1.jpg Destination: C:\users\js\19981016\19981016_0001.jpg".
What if: Performing the operation "Rename File" on target "Item: C:\users\js\19981016\file10.jpg Destination: C:\users\js\19981016\19981016_0002.jpg".
What if: Performing the operation "Rename File" on target "Item: C:\users\js\19981016\file2.jpg Destination: C:\users\js\19981016\19981016_0003.jpg".
js2010
  • 23,033
  • 6
  • 64
  • 66
0
$path="C:\..."
$files=Get-ChildItem $path -Filter *.gif  
Foreach($obj in $files){
   $pathWithFilename=$path + $obj.Name;
   $newFilename= "file_"+$obj.Name; 

   Rename-Item -Path $pathWithFilename -NewName $name
}

You can use this code blocks in powershell ISE. Example output like this :

Old files :

1232.gif asd.gif

After run code :

file_1232.gif file_asd.gif

MahmutKarali
  • 339
  • 4
  • 8