Trim date from file name using powershell or cmd - powershell

How do you trim the date from a text file. For example, I have multiple files like:
test_20091011.txt
try_20091011.txt
fold_20091011.txt
I would like to change into:
test.txt
try.txt
fold.txt
Thanks.

This code should work assuming the text file name format doesn't change, as in, it's always the last 9 characters you need to remove. This code assumes the txt files are in the folder C:\folder
$filelist = (get-childitem c:\folder | Where-Object {$_.mode -match "a"} | foreach-object {$_.name})
foreach ($file in $filelist)
{
$len = $file.length
$newname = $file.substring(0,$len -13)
$newname = $newname + '.txt'
Rename-Item C:\folder\$file $newname
clear-variable newname, len
}

The answer for this will change subtly depending on the type of naming pattern, but in your case, you can accomplish this with a script like this:
Get-ChildItem |
Where-Object {
<#
Multiple Assignment in PowerShell.
$beforeUnderbar will have your name,
$AfterUnderBar will have the data, and
$extension will have the extension.
All from one little -split
If you start throwing random other files in there, it will barf.
#>
$beforeUnderbar, $afterUnderBar, $extension = ($_.Name -split "[_.]")
if ($afterUnderBar -and $afterUnderBar.Length -eq 8 -and $afterUnderBar -as [int]) {
"$beforeUnderBar.$extension"
}
}
That script should give you what you want from files that match your naming convention.

Related

Powershell rename files whilst maintaining the original file order

I've got a set of files in the following format
I'd like to change the file names to the following format
I've used the following code:
`$i = 21
dir | ForEach-Object {$_ | Rename-Item -NewName ('00816-101998-XX-A-2-50-{0:D3} Detalj.{1}' -f $i++, $_.Extension)}`
This code starts renaming with file name A.10.11.11
How do I get it to start from the first file name i.e. 8.A.10.11.8?
Thank you!
Looking at your question, I think this is what you intend to do.
The list of current filenames should be sorted by the integer value the filenames start with.
Next you want to rename them using a counter that starts with value 21
To do this, you can use a ForEach-Object loop, but the -NewName parameter of Rename-Item can also contain a scriptblock containing the action to perform.
$i = 21
(Get-ChildItem -Path 'D:\Test' -Filter '*.pdf' -File) |
Sort-Object #{Expression = {[int]($_.Name -split ' ')[0]}} |
Rename-Item -NewName { '00816-101998-XX-A-2-50-{0:D3} Detalj{1}' -f $script:i++, $_.Extension }
P.S. The image shows the filename starts with a number followed by a space, while in the question you give an example where the number is followed by a dot .. If that is the case in you file names, change [int]($_.Name -split ' ')[0] into [int]($_.Name -split '\.')[0]
1. We need to address and increment the value of the counter $i using the $script:i scoping syntax, otherwise $i does not exist in the NewName scriptblock
2. To avoid renaming files twice, enclose the Get-ChildItem part in the code in between brackets
param(
$directory = "d:\tmp",
[regex]$rx = "(?<=8.A.10.11.)\d+",
[string]$newPrefix = "00816-101998-XX-A-2-50-"
)
<#
8..20 | ForEach-Object {
$filePath = Join-Path $directory -ChildPath "8.A.10.11.$_.pdf"
Out-File -InputObject "some text" -FilePath $filePath -Encoding default
}
#>
Get-ChildItem $directory | ForEach-Object{
Rename-Item $_.FullName -NewName "$newPrefix$((($rx.Matches($_.BaseName)).value).padleft(3,'0'))$($_.Extension)"
}

Correction in sub folder names by replacing first two characters, if needed

I am using below Powershell script which successfully traverses through all my case folders within the main folder named Test. What it is incapable of doing is to rename each sub folder, if required, as can be seen in current and desired output. Script should first sort the sub folders based on current numbering and then give them proper serial numbers as folder name prefix by replacing undesired serial numbers.
I have hundreds of such cases and their sub folders which need to be renamed properly.
The below output shows two folders named "352" and "451" (take them as order IDs for now) and each of these folders have some sub-folders with a 2 digit prefix in their names. But as you can notice they are not properly serialized.
$Search = Get-ChildItem -Path "C:\Users\User\Desktop\test" -Filter "??-*" -Recurse -Directory | Select-Object -ExpandProperty FullName
$Search | Set-Content -Path 'C:\Users\User\Desktop\result.txt'
Below is my current output:
C:\Users\User\Desktop\test\Case-352\02-Proceedings
C:\Users\User\Desktop\test\Case-352\09-Corporate
C:\Users\User\Desktop\test\Case-352\18-Notices
C:\Users\User\Desktop\test\Case-451\01-Contract
C:\Users\User\Desktop\test\Case-451\03-Application
C:\Users\User\Desktop\test\Case-451\09-Case Study
C:\Users\User\Desktop\test\Case-451\14-Violations
C:\Users\User\Desktop\test\Case-451\21-Verdict
My desired output is as follows:
C:\Users\User\Desktop\test\Case-352\01-Proceedings
C:\Users\User\Desktop\test\Case-352\02-Corporate
C:\Users\User\Desktop\test\Case-352\03-Notices
C:\Users\User\Desktop\test\Case-451\01-Contract
C:\Users\User\Desktop\test\Case-451\02-Application
C:\Users\User\Desktop\test\Case-451\03-Case Study
C:\Users\User\Desktop\test\Case-451\04-Violations
C:\Users\User\Desktop\test\Case-451\05-Verdict
Thank you so much. If my desired functionality can be extended to this script, it will be of great help.
Syed
You can do the following based on what you have posted:
$CurrentParent = $null
$Search = Get-ChildItem -Path "C:\Users\User\Desktop\test" -Filter '??-*' -Recurse -Directory | Where Name -match '^\d\d-\D' | Foreach-Object {
if ($_.Parent.Name -eq $CurrentParent) {
$Increment++
} else {
$CurrentParent = $_.Parent.Name
$Increment = 1
}
$CurrentNumber = "{0:d2}" -f $Increment
Join-Path $_.Parent.FullName ($_.Name -replace '^\d\d',$CurrentNumber)
}
$Search | Set-Content -Path 'C:\Users\User\Desktop\result.txt'
I added Where to filter more granularly beyond what -Filter allows.
-match and -replace both use regex to perform the matching. \d is a digit. \D is a non-digit. ^ matches the position at the beginning of the string.
The string format operator -f is used to maintain the 2-digit requirement. If you happen to reach 3-digit numbers, then 3 digit numbers will be output instead.
You can take this further to perform a rename operation:
$CurrentParent = $null
Get-ChildItem . -Filter '??-*' -Recurse -Directory | Where Name -match '^\d\d-\D' | Foreach-Object {
if ($_.Parent.Name -eq $CurrentParent) {
$Increment++
} else {
$CurrentParent = $_.Parent.Name
$Increment = 1
}
$CurrentNumber = "{0:d2}" -f $Increment
$NewName = $_.Name -replace '^\d\d',$CurrentNumber
$_ | Where Name -ne $NewName | Rename-Item -NewName $NewName -WhatIf
}
$NewName is used to simply check if the new name already exists. If it does, a rename will not happen for that object. Remove the -WhatIf if you are happy with the results.

How to remove first word from folder name?

I have 26 folders with the names of my students (Firstname Lastname_somedata). Windows sorts this with their first name. I want to automate the deletion of their first name so their last last name comes first and sorts like it should.
Thanks!
Edit: An Example folder name "Anna Ansaleere_28032_assignsubmission_file_".
I have been trying some stuff but nothing that actually produced something usefull.
As commented, it would be better to have the first- and lastnames swapped with a comma in between. That way the possibility of ending up with duplicate folder names is rather unlikely.
I'd suggest something like this:
$rootFolder = 'D:\Test'
Get-ChildItem -Path $rootFolder -Directory | ForEach-Object {
$student, $remainder = $_.Name -split '_', 2
# in case there is a folder where no space is found between the First and Last name
if (!($student.Contains(' '))) {
Write-Host "Not possible to find the First and Lastname in $($_.FullName)"
continue
}
$firstname, $lastname = $student -split ' ', 2
$newName = '{0}, {1}_{2}' -f $lastname, $firstname, $remainder
$_ | Rename-Item -NewName $newName -WhatIf
}
If you are satisfied with the resuts shown in the PowerShell console, remove the -WhatIf switch so the folders are actually renamed.
Before:
Anna Ansaleere_28032_assignsubmission_file
Henry This-Or-That_98765_assignsubmission_file
John Doe_12345_rejection_file
After:
Ansaleere, Anna_28032_assignsubmission_file_
Doe, John_12345_rejection_file
This-Or-That, Henry_98765_assignsubmission_file
P.S. if your version of PowerShell is less than 3.0, do Get-ChildItem -Path $rootFolder | Where-Object { $_.PSIsContainer } | ForEach-Object {..} to return directories only
With the assumption that "somedata" do not contain a space (studentID parhaps?) this would work.
$folder_path = "C:\Users\USER\Documents\stackoverflow"
#Gets all folders from $folder_path location.
$folders = Get-ChildItem $folder_path | where {$_.PSIsContainer -eq $true}
foreach ($folder in $folders)
{
#Takes the second string after spliting it on "space" character.
#In case of: Jonas Olsson_1452385
#The second string would be: Olsson_1452385
$new_name = ($folder.name).split(" ")[1]
$new_name
#Rename folder to new name
Rename-Item $folder.FullName -NewName $new_name
}
PS, next time, let us know what you have tried when you post.

In power shell, how to replicate the action I do in a folder to other folders?

The action I am supposed to do:
Read a file from a folder
Extract a date from the 1st line
Change it to 'yyyymmdd' format
Rename all the file by removing first 4 characters and place this format date at the beginning.
Example FILE.FILE will be changed to 20180725.FILE (The date will be in the file)
I am able to accomplish this to a single folder in Newpath by the following code:
$path="\\Data\DEV\DevDat\Arun\DXSL\Newpath\20170601"
$files=Get-ChildItem $path | Select-Object -first 1
$data = Get-Content "$path\$files" -first 1
foreach($line in $data)
{
$arr = $line.substring(52,4)+$line.substring(46,2)+$line.substring(49,2)
}
get-childitem $path | rename-item -newname { $arr +[string]($_.name).substring(4)}
However, I am not able to replicate this action to the other folders in a loop. The Newpath folder has several sub-folders. I need to rename the files inside each sub-folder inside Newpath. Is there any way to achieve this?
FYI I'm using Version 4 of powershell.
A PowerShell script as suggested in my comment.
It does not check if the file to rename to already exists.
The Rename-Item has the parameer -WhatIf appended, so it only shows what would be done.
If there are more numbers in the first line, the script will match the first pattern.
The script also does not check if the file already is renamed to the pattern.
## Q:\Test\2018\07\25\SO_51522205.ps1
#Requires -Version 3.0
$BasePath = "\\Data\DEV\DevDat\Arun\DXSL\Newpath"
$RE = [RegEx]'(?<Month>\d{2}).(?<Day>\d{2}).(?<Year>\d{4})'
ForEach ($Folder in (Get-ChildItem -Path "$BasePath\*" -Directory)){
ForEach ($File in (Get-ChildItem -Path "$($Folder.FullName)\*" -File)){
$Line1 = (Get-Content $File.FullName | Select-Object -First 1)
If ($File.BaseName.Length -gt 4){
$BaseName = $File.BaseName.SubString(4)
} else {
$BaseName = ''
}
If ($Line1 -match $RE){
$NewName = ("{0}{1}{2}{3}{4}" -f `
$Matches.Year,
$Matches.Month,
$Matches.Day,
$BaseName,
$File.Extension)
$File | Rename-Item -NewName $NewName -WhatIf
} Else {
"{0} doesn't have a proper date in 1st line" -f $File.FullName
}
}
}
Sample tree before,
> tree /F
└───Newpath
└───20170601
blahblah.txt
FILE.FILE
after running the script.
> tree /F
└───Newpath
└───20170601
20180724blah.txt
20180725.FILE

Programmatically edit file names to remove leading text

I have a variety of files with names in the directory that look like this:
first_file_123456.jpg
5 * second_file_246531 (2).jpg
What I am looking to do is lay my hands on a PowerShell script that can take these files and rename them like this:
123456.jpg
246531 (2).jpg
I am looking to strip the last underscore and all text leading up to it to rename my files so they can match item numbers in my enterprise resource planning system. This system is much older (2004 technology) so automating from that side is out.
What i have tried to wire up so far and does not seem to work properly is as follows:
Get-ChildItem -Recurse -filter *_* | `
Foreach-Object {
$oldName = $_.Name
$pos = $oldName.LastIndexOf("_")
$newName = $oldName.Substring($pos + 1)
if (Test-Path $newName) {
# This is where I get lost - if it runs into a duplicate file name
# how can I make the name unique
}
#write-host $_.fullname
write-host $oldName renamed To: $newName | Out-File renamelog.txt
#rename-item $_.FullName -NewName $newName
}
I commented out the commands that actually do something to see what the output is.
Enumerate your files, filter for filenames containing an underscore, then rename them with everything up to and including the last underscore removed.
$re = '^.*_'
Get-ChildItem 'C:\some\folder' |
Where-Object { $_.Name -match $re } |
Rename-Item -NewName { $_.Name -replace $re }
Here's a short demo that uses the LastIndexOf and Substring methods:
$name = "first_file_123456.jpg"
$indexOfLastUnderscore = $name.LastIndexOf("_")
$newName = $name.Substring($indexOfLastUnderscore + 1, $name.Length - $indexOfLastUnderscore - 1)
# $newName now contains "123456.jpg"
Here's another way that uses PowerShell's -split operator and array indexing:
$name = "first_file_123456.jpg"
$newName = ($name -split '_')[-1]
$newName
# $newName now contains "123456.jpg"
Batch rename:
Get-Childitem -path $startDir -recurse |
where { ! $_.PSIsContainer } |
foreach {
$newName = Join-Path $_.Directory ($_.Name -replace '.*_', '');
Rename-Item $_.FullName $newName;
};