How to remove first word from folder name? - powershell

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.

Related

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 copy files using a txt list to define beginning of file names

Hello awesome community :)
I have a list containing a bunch of SKU's. All the filenames of the files, that I need to copy to a new location, starts with the corresponding SKU like so
B6BC004-022_10_300_f.jpg
In this case "B6BC004" is the SKU and my txt list contains "B6BC004" along with many other SKU's.
Somewhere in the code below I know I have to define that it should search for files beginning with the SKU's from the txt file but I have no idea how to define it.
Get-Content .\photostocopy.txt | Foreach-Object { copy-item -Path $_ -Destination "Z:\Photosdestination\"}
Thanks in advance :)
If all files start with one of the SKU's, followed by a dash like in your example, this should work:
$sourceFolder = 'ENTER THE PATH WHERE THE FILES TO COPY ARE'
$destination = 'Z:\Photosdestination'
# get an array of all SKU's
$sku = Get-Content .\photostocopy.txt | Select-Object -Unique
# loop through the list of files in the source folder and copy all that have a name beginning with one of the SKU's
Get-ChildItem -Path $sourceFolder -File -Recurse |
Where-Object { $sku -contains ($_.Name -split '\s*-')[0] } |
ForEach-Object { $_ | Copy-Item -Destination $destination }
I haven't tested this so please proceed with caution!
What is does it loops through all the items in your photostocopy.txt file, searches the $source location for a file(s) with a name like the current item from your file. It then checks if any were found before outputting something to the console and possibly moving the file(s).
$source = '#PATH_TO_SOURCE'
$destination = '#PATH_TO_DESTINATION'
$photosToCopy = Get-Content -Path '#PATH_TO_TXT_FILE'
$photosToCopy | ForEach-Object{
$filesToCopy = Get-ChildItem -Path $source -File | Where-Object {$_.Name -like "$_*"}
if ($fileToCopy.Count -le 0){
Write-Host "No files could be found for: " $_
}else{
$filesToCopy | ForEach-Object{
Write-Host "Moving: " $_.Name
Copy-Item -Path $_.FullName -Destination $destination
}
}
}
Let me know how if this helps you :)

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;
};

Adding leading zeros to file name strings using PowerShell

I'm new to using PowerShell and am wondering how to simply pad number strings contained in several similar file names to have the same number of digits in each file name.
That is, I have a folder containing these 300 files:
dummy name 1.txt through dummy name 300.txt
and would simply like rename the files that have less than 3 digits in them to all have exactly 3 digits, such as:
dummy name 001.txt through dummy name 300.txt
If your files were produced sequentially and you've got name1.txt
, name2.txt, etc.,
And you want name0001.txt, name0002.txt, etc.
You can do
$j=1;
foreach ($i in Get-ChildItem "./name?.txt" -Name) {
echo $i;
$new_name = "name000" + $j + ".txt";
Rename-Item -Path $i -NewName $new_name;
$j=$j+1;
}
... Then do it again, changing $j to 10 at the start, taking a 0 off, and so on for the hundreds.
Okay for a one off and if you can then fix what's producing the files in the first place.
#TessellatingHeckler gave good answer in the comments:
gci | ren -n {[regex]::replace($_.name, '\d+', {"$args".PadLeft(3, '0')})}
I would do it like this:
$i=0;
$nameLike='dummy name'
[int]$currentid=0
#RENAME TO REMOVE THE SPACE IN THE MIDDLE
gci -File -Path "./" | where{ $_.name -like "$nameLike*"} | %{
#remove space in the middle
$newname = $_.Name.Split(' ')[0] + $_.Name.Split(' ')[1]
#convert the name into the padding you want (3)
[int]::TryParse($_.Name.Split(' ')[2].Split('.')[0],[ref]$CurrentId) | Out-Null
$newname = $newname + $CurrentId.ToString("000") + $_.Extension
Rename-Item -Path $_.FullName -NewName $newname
}
Details in here:
https://medium.com/#josegabrielortegac/powershell-renaming-files-with-powershell-e9012573647a?sk=502148e039058d84fe34608d77cd1aa2
Try this:
1..300 | %{
$source = "dummy name $_.txt"
$target = ('dummy name {0:00#}.txt' -f $_)
rename-item $source -NewName $target
}
Notes:
The outer loop is a little unconventional. Most scripters code this to resemble a java for loop.
The choice of single and double quotes is intentional. Be careful.
The code is a little inelegant, because some parts of the filename are typed in twice.
The assumption is that all 300 files exist. If not, you will get errors.
try this:
Get-ChildItem "c:\temp\" -file -Filter "*.txt" | where basename -match ". \d{1,2}$" | %{
$res=$_.BaseName -split '(.)(\d{1,2})$'
$newnamme="{0}\{1} {2:D3}{3}" -f $_.Directory, $res[0], [int]$res[2], $_.Extension
Rename-Item $_.FullName $newnamme
}

Trim date from file name using powershell or cmd

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.