1

I'm a complete noob when it comes to powershell but I've been struggling with this one all day and not sure why.

Each day, I will have a set of files in a directory. The files will be different names and different extesions so they are all unique. I'm trying to rename all of those files to contain the same initial file name and then put the current date time at the end and not include an extension. Below is what I have. I browse to the directory my files reside in, create my variable for getting the current date time and formatted the way I want. I then issue my command to rename and it always errors out after doing the first file successfully as it tries to edit the first file again which was already renamed. Any help would be greatly appreciated. Thanks in advance.

Example File Names to be renamed

test123.dat
341test.txt
983asdf.doc

Desired End Result which each file being unique with the millisecond that you can see as the end 4 numbers in the file name below:

abcabcp123456789d202004271552001023
abcabcp123456789d202004271552001024
abcabcp123456789d202004271552001025

What I tried:

$curDateTime = Get-Date -Format yyyyMMddTHHmmssffff
Get-ChildItem *.* | Rename-Item -NewName {'abcabcp123456789d' + $curDateTime}

If I run a -WhatIf, it says it works fine with no errors. When I actually run it, it says: Rename-Item : Cannot create a file when that file already exists.

Is it too quick even for the milliseconds? In the -WhatIf, even though it says there aren't errors, all three files show up with the same name. Any way around that. Thanks again.

Updated Variation I tried running:

Get-ChildItem *.* | ForEach { 
    Rename-Item -Path $_.FullName -NewName "$($_.DirectoryName)\$('abcabcp123456789d')$(Get-Date -F yyyyMMddTHHmmssffff)" 
}

Tried the code with parenthsis:

(Get-ChildItem *.*) | ForEach { Rename-Item -Path $_.FullName -NewName "$($_.DirectoryName)\$('abcabcp123456789d')$(Get-Date -F yyyyMMddTHHmmssffff)"}

New code with parenthesis that didn't work. I received an error of:

Rename-Item : Cannot create a file when that file already exists. At line:1 char:33 + (Get-ChildItem .) | ForEach { Rename-Item -Path $.FullName -NewName "$($.Dir ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : WriteError: (F:\abc\Test\Upl...00415-b-dbo:String) [Rename-Item], IOException + FullyQualifiedErrorId : RenameItemIOError,Microsoft.PowerShell.Commands.RenameItemCommand

  • [1] wrap your call to Get-ChildItem in parens () to force it to read the entire list FIRST. [2] you need to calc the datestamp for each new file ... you are only calculating it once. [grin] – Lee_Dailey Apr 28 at 0:17
  • Thanks Lee. I tried doing as you said but still couldn't figure it out. I'm new to powershell so it's not clicking. I found another variation of what I was trying and can get it to work for 1 file all the time and sometimes 2 files but never all 3 files. It errors out with cannot create a file as that file already exists. Below is the command: Get-ChildItem . | ForEach { Rename-Item -Path $_.FullName -NewName "$($_.DirectoryName)\$('ACHACHP273974549TD')$(Get-Date -F yyyyMMddTHHmmssffff)" } – JK_PShell_Noob Apr 28 at 13:07
  • you are welcome! [grin] you need to post your added/updated code in your Question so folks can see it ... and wrap it in code formatting so that folks can actually read it. [grin] ///// also, you need to force Get-ChildItem to read all the files at one pass by encloding that part of your pipeline in () to make it run entirely before it passes any file into to the next pipeline stage. – Lee_Dailey Apr 28 at 13:20
  • Thanks Lee. I've updated my original question to include the latest powershell command and results. Unfortunately I'm either not doing it as you are asking or it just didn't correct my situation. Thanks again, I do appreciate the help. – JK_PShell_Noob Apr 28 at 15:03
  • i posted an Answer that uses a normal loop instead of the pipeline. that avoids the "read in sequence/read all at once" problem entirely. however, your computer may be fast enuf that it will still have name collisions. is so, see my comment about adding a delay in the foreach loop. – Lee_Dailey Apr 28 at 15:41
0

this does the job in a slightly different way. by taking things OUT of the pipeline and using a normal loop, you can get a bit more direct control and see what each step is doing a tad more clearly. [grin]

what it does ...

  • sets the constants [source dir & file name prefix]
  • creates some test files
    when you are ready to do this with your test data, simply remove the entire #region/#endregion block.
  • grabs the files in the $SourceDir
  • iterates thru those files
  • gets the suffix date stamp
  • builds the new file name
  • builds the FULL new file name [includes the path]
  • renames the file

there are no outputs. errors are suppressed in the "make test files" area, but you should see error msgs for any other problems.

the test files are roughly 2-15 milliseconds apart. if your system is fast enuf, then you may need to add a Start-Sleep command just before the $Suffix line. perhaps something like Start-Sleep -Milliseconds 10.

i also added an underscore between the $Prefix and the $Suffixto make it easier for me to read. you can remove that by changing the-join '_'to-join ''`.

the code ...

$SourceDir = "$env:TEMP\TestingStuff"
$Prefix = 'abcabcp123456789d'

#region >>> create test files to work with
#    when ready to do test with real data, remove this entire block
$Null = mkdir -Path $SourceDir -ErrorAction 'SilentlyContinue'
@('test123.dat'
    '341test.txt'
    '983asdf.doc'
    ) |
    ForEach-Object {
        $Null = New-Item -Path $SourceDir -Name $_ -ItemType 'File' -ErrorAction 'SilentlyContinue'
        }
#endregion >>> create test files to work with

$FileList = Get-ChildItem -LiteralPath $SourceDir -File

foreach ($FL_Item in $FileList)
    {
    $Suffix = (Get-Date).ToString('yyyyMMddTHHmmssfff')
    $NewName = $Prefix, $Suffix -join '_'
    $FullNewName = Join-Path -Path $SourceDir -ChildPath $NewName

    Rename-Item -LiteralPath $FL_Item.FullName -NewName $FullNewName
    }

the renamed files ...

"C:\Temp\TestingStuff\abcabcp123456789d_20200428T102747124"
"C:\Temp\TestingStuff\abcabcp123456789d_20200428T102747126"
"C:\Temp\TestingStuff\abcabcp123456789d_20200428T102747117"
| improve this answer | |
  • Lee, Thankyou, Thankyou, Thankyou!! I've been racking my brain with research and you helped me through it and put it in a format that was easy to understand. I did end up adding the Start-Sleep component which allowed me to rename all files as intended. Again, I appreciate all the help and being patient with me. Take care. – JK_PShell_Noob Apr 28 at 16:11
  • @JK_PShell_Noob - you are most welcome! glad to help ... and you may want to mark the Answer as accepted so others can find it more easily. – Lee_Dailey Apr 28 at 19:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.