I have some long filenames that potensially can cause issues with Windows path max chars, and I would like to rename them preserving part of it - and also adding a RNG 4 letter/digit combination.
Filename example: 478432_1400_79834_SomeKindofText_UserInputSoItCanBeReallyLongCombinedWithANetworkPath.jpg
Wanted rename outcome:
478432_1400_79834_SomeKindofText_abc1.jpg
Where 'abc1' represents the 4 letter/digit combination of a checksum
This is the code I have so far:
$search_folder = "C:\PS\Test\"
Get-ChildItem $search_folder -File | ForEach-Object {
$checksum = Get-FileHash -Path $_
$checksum = $checksum.substring(0,3)
Rename-Item -NewName { $search_folder $_.BaseName.Split('_')[0..3] $checksum $_.Extension }
}
My first problem is that Get-FileHash
does not support substring method, generating a error message:
Method invocation failed because [Microsoft.Powershell.Utility.FileHash] does not contain a method named 'substring'.
My second problem is that it tries to do a Resolve-Path in my current PS shell directory instead of $search_folder
My third problem is that the underscores in the filename is not preserved, so a -WhatIf tag on the Rename-Item method yields a result like "478432 1400 79834 SomeKindofText"
Tips or suggestions would be most welcomed!
CodePudding user response:
My first problem is that Get-FileHash does not support substring method, generating a error message:
Method invocation failed because [Microsoft.Powershell.Utility.FileHash] does not contain a method named 'substring'.
$checksum
does not store the hash string, it stores an object that has a property named Hash
, which in turn stores the string you want, so change this line:
$checksum = $checksum.substring(0,3)
To:
$checksum = $checksum.Hash.Substring(0,3)
My second problem is that it tries to do a Resolve-Path in my current PS shell directory instead of $search_folder
Two general solutions to this problem:
Pass the absolute path to the file explicitly:
Rename-Item -LiteralPath $_.FullName -NewName { ... }
Or pipe the output from
Get-ChildItem
directly toRename-Item
and let PowerShell bind the path correctly:$_ |Rename-Item -NewName { ... }
My third problem is that the underscores in the filename is not preserved, so a -WhatIf tag on the Rename-Item method yields a result like "478432 1400 79834 SomeKindofText"
Splitting a string on '_'
will also remove the underscores - to reverse this, use '_'
as a delimiter in a -join
operation:
$firstFourPartsOfBaseName = $_.BaseName.Split('_')[0..3] -join '_'
Putting this all together, we get:
$search_folder = "C:\PS\Test\"
Get-ChildItem $search_folder -File | ForEach-Object {
$checksum = Get-FileHash -Path $_
$checksum = $checksum.hash.substring(0,3)
$_ |Rename-Item -NewName {
# calculate new base name ("478432_1400_79834_SomeKindofText_abc1")
$newBasename = @($_.BaseName.Split('_')[0..3]; $checksum) -join ''
# add extension and output
$newBasename,$_.Extension -join '.'
}
}
CodePudding user response:
Please see your script adjusted below:
$search_folder = "C:\PS\Test\"
Get-ChildItem $search_folder -File | ForEach-Object {
$checksum = Get-FileHash -Path $_
$checksum = $checksum.hash.substring(0,3)
Rename-Item -Path $_ -NewName ($search_folder $_.BaseName.Split('_')[0..3] $checksum $_.Extension)
}
You were trying to get a sub string of an object, using the property hash
on $Checksum
will allow you to create a substring.
I have also added -path
to the rename-item
request and changed the parenthesis on the string construction (it could be either of these that were causing you an issue, unfortunately I haven't tested this.)