The following code works beautifully:
Get-ChildItem -Path E:\Videos\Movies\ -File -Include *.avi,*.mp4,*.mkv -Recurse | Rename-Item -NewName { $_.Name.replace("DVDRIP","DVD") }
Now, 2 questions:
Anyway I can input multiple words to replace to DVD? Here is what I was thinking:
Get-ChildItem -Path E:\Videos\Movies\ -File -Include *.avi,*.mp4,*.mkv -Recurse | Rename-Item -NewName { $_.Name.replace("DVDRIP|DVDR|DVD5|DVD9","DVD") }
I have tried this and other variations, but I just can't figure it out.
How can I make the code NOT case sensitive so I don't have multiple lines trying to catch the possible different spellings?
You are using a regex-pattern with a normal text-replace method. Try -replace which is made for regex. -replace is also case-insensitive by default.
Get-ChildItem -Path E:\Videos\Movies\ -File -Include *.avi,*.mp4,*.mkv -Recurse |
Rename-Item -NewName { $_.Name -replace "DVDRIP|DVDR|DVD5|DVD9","DVD" }
Related
I have some files such as:
20220716_165615-IMG_1234.jpg
20220717_102742-IMG_1235.jpg
20220717_193212-IMG_1236.jpg
They need to be renamed to:
2022-07-16_16.56.15-IMG_1234.jpg
2022-07-17_10.27.42-IMG_1235.jpg
2022-07-17_19.32.12-IMG_1236.jpg
I tried using a rename in Windows 10 CMD:
ren ????????_??????-*.* ????-??-??_??.??.??-*.*
But I was not successful.
Turns out it's easier with windows powershell:
for the current folder:
Get-Item .\*.* | Rename-Item -NewName {$_.BaseName.insert(15,'.') + $_.Extension} -WhatIf
Get-Item .\*.* | Rename-Item -NewName {$_.BaseName.insert(13,'.') + $_.Extension} -WhatIf
Get-Item .\*.* | Rename-Item -NewName {$_.BaseName.insert(6,'-') + $_.Extension} -WhatIf
Get-Item .\*.* | Rename-Item -NewName {$_.BaseName.insert(4,'-') + $_.Extension} -WhatIf
for the contents of the subfolders:
Get-ChildItem -File -Recurse | Rename-Item -NewName {$_.BaseName.insert(11,'.') + $_.Extension} -WhatIf
Get-ChildItem -File -Recurse | Rename-Item -NewName {$_.BaseName.insert(6,'-') + $_.Extension} -WhatIf
Get-ChildItem -File -Recurse | Rename-Item -NewName {$_.BaseName.insert(4,'-') + $_.Extension} -WhatIf
(the -WhatIf argument shows what's about to be done. To execute it for real, remove the -WhatIf argument)
I tried following Remove leading spaces in Windows file names but it's not working for my use case.
I have a lot of folders and filenames that either have a blank space at the front or at the end. How would I go about removing those spaces in bulk?
This was the command-line command I used after following the linked post:
for /R %A IN ("* ") do #for /F "tokens=*" %B IN ("%~nxA") do #ren "%A" "%B"
But it didn't work out.
Update: thank you to all who replied trying to help. I think there is just a Windows-level glitch in the file system. I ended up just having to manually create new folders without leading and trailing spaces and then dragging all the files over manually then renaming those to non-trailing and leading names as well.
It's unclear whether or not you want a PowerShell solution, but there's a reasonable assumption to be made you might.
If you wanted a PowerShell solution, you could try this:
function Test-LeadingTrailingWhitespace {
param(
[Parameter(Mandatory)]
[String]$String
)
$String[0] -eq ' ' -Or $String[-1] -eq ' '
}
Get-ChildItem -Path "<path_to_folder>" | ForEach-Object {
if ($_.PSIsContainer -And (Test-LeadingTrailingWhitespace -String $_.Name)) {
$Destination = Split-Path -Path $_.FullName -Parent
$NewName = $_.Name.Trim()
Move-Item -Path $_ -Destination (Join-Path -Path $Destination -ChildPath $NewName)
}
elseif (Test-LeadingTrailingWhitespace -String $_.BaseName) {
$Destination = Split-Path -Path $_.FullName -Parent
$NewName = $_.BaseName.Trim() + $_.Extension
Move-Item -Path $_ -Destination (Join-Path -Path $Destination -ChildPath $NewName)
}
}
To be on the safe side, you could add -WhatIf or -Confirm on the Move-Item cmdlet. The former will tell you what would have changed without that parameter without actually making any changes (like a 'dry run'). The latter will prompt you for confirmation before making each change, giving you a chance to validate incrementally and not make changes en masse from the moment you hit enter.
Trim() is a method available for all strings in PowerShell:
Returns a new string in which all leading and trailing occurrences of a set of specified characters from the current string are removed.
You can loop over files and folder and check if they actually have a leading or trailing whitespace before renaming, this would avoid errors like:
Rename-Item: Source and destination path must be different.
We can use the -match matching operator with a simple regex ^\s|\s$ (starts with whitespace or ends with whitespace - regex101 link for a simple example) to see if the file or folder should be renamed:
Get-ChildItem path\to\startingfolder -Recurse | ForEach-Object {
$newName = switch($_) {
# handle folders
{ $_.PSIsContainer -and $_.Name -match '^\s|\s$' } {
$_.Name.Trim()
break
}
# handle files
{ $_.BaseName -match '^\s|\s$' -or $_.Extension -match '^\s|\s$' } {
$_.BaseName.Trim() + $_.Extension.Trim()
break
}
# if none of the above conditions were true, continue with next item
Default {
return
}
}
Rename-Item -LiteralPath $_.FullName -NewName $newName
}
Personally, I'd do this in two steps to rename folders and files separately. This to overcome the problem that when a folder is renamed, the items inside that folder all have a new path.
Using switch -Force allows renaming items such as hidden or read-only files
Using -ErrorAction SilentlyContinue swallows the error when the new name is equal to the existing name
$rootPath = 'X:\thepath'
# first the folders and subfolders (deepest nesting first)
(Get-ChildItem -Path $rootPath -Directory -Recurse | Sort-Object FullName -Descending) |
Rename-Item -NewName {$_.Name.Trim()} -Force -ErrorAction SilentlyContinue
# next the files
(Get-ChildItem -Path $rootPath -File -Recurse) |
Rename-Item -NewName {'{0}{1}' -f $_.BaseName.Trim(), $_.Extension.Trim()} -Force -ErrorAction SilentlyContinue
I'm looking at how to add an extension recursively to an entire folder structure. This line does what I need, but only for the current folder. I need to do the same for the subfolders structure.
Get-ChildItem -File | % { mv ($_.BaseName+"") ($_.BaseName+".png") }
But I keep getting this error:
Cannot find path 'C:\Users\Jess...\' because it does not exist.
I used the search, however I only founded a solution for the Bash, not the PowerShell. So I couldn't get the -Recurse to work in the same way.
Get-ChildItem -File -Recurse | % { mv ($_.BaseName+"") ($_.BaseName+".png") }
Here's a way to get the full pathname. In powershell 6 this isn't an issue.
Get-ChildItem -File -Recurse | % { $_ | mv -destination ($_.Name + '.png' ) -whatif }
Or
Get-ChildItem -File -Recurse | ? { ! $_.extension } |
mv -destination { $_.Name + '.png' } -whatif
I want to search all drives using PowerShell on windows machine to get the list of all files along with their extensions -
Based on desired extension we pass in it like - *.mp3 or
Fetch all files with multiple extensions like - *.txt, *.mp3 etc.
I tried below script but its giving only information from where we are running it. But I want to scan whole machine.
Get-ChildItem -Path .\ -Filter ***.doc** -Recurse -File| Sort-Object Length -Descending | ForEach-Object { $_.BaseName }
Checkout the Get-PSDrive cmdlet. It returns a list of drives, and you can specify just disk drives with the -PSProvider FileSystem parameter:
foreach ( $drive in $(Get-PSDrive -PSProvider FileSystem) ) {
Get-ChildItem -Path $drive.Root -Filter ***.doc** -Recurse -File |
Sort-Object Length -Descending |
ForEach-Object { $_.BaseName }
}
Didn't test that but you get the idea.
Using -Include on Get-ChildItem will allow you to specify a list of extensions. The -ErrorAction will cause it to skip drives that are not available such as an unmounted CD drive.
Get-PSDrive -PSProvider FileSystem |
ForEach-Object {
Get-ChildItem -Path $_.Root -Recurse -Include '*.doc*', '*.txt' -ErrorAction SilentlyContinue |
ForEach-Object { $_.Name }
} |
ForEach-Object {[PSCustomObject]#{HashCode = $_.GetHashCode(); FullName = $_.FullName}}
} |
Export-Csv -Path $TempFile -NoTypeInformation -Encoding ASCII
Update:
Here is a better way. It will prevent unknown extensions from getting into the mix such as "Microsoft.NET.Sdk.Publish.Docker.targets."
$ExtensionList = #('.txt', '.doc', '.docx', '.mp3')
$TempFile = Join-Path -path $Env:TEMP -ChildPath "$($pid.ToString()).tmp"
Get-PSDrive -PSProvider FileSystem |
ForEach-Object {
Get-ChildItem -Path $_.Root -Recurse -ErrorAction SilentlyContinue |
Where-Object { $ExtensionList -contains $_.Extension } |
ForEach-Object {
[PSCustomObject]#{
HashCode = $_.GetHashCode();
DirectoryName = $_.DirectoryName
Name = $_.Name
}
}
} |
Export-Csv -Path $TempFile -Delimiter ';' -NoTypeInformation -Encoding ASCII
Write-Host "The temp file is $TempFile"
This is more than what the original question asked, but if you are going to go through the trouble of listing all your files, I suggest getting the filehash as well so you can determine if you have duplicates. A simple file name search will not detect if the same file has been saved with a different name. Adding to what #lit (https://stackoverflow.com/users/447901/lit) has posted:
$ExtensionList = #('.txt', '.doc', '.docx', '.mp3')
Get-PSDrive -PSProvider FileSystem |
ForEach-Object {
Get-ChildItem -Path $_.Root -Recurse -ErrorAction SilentlyContinue |
Where-Object { $ExtensionList -eq $_.Extension } |
## ForEach-Object { $_.Name, $_.FullName, $_.GetHashCode() }
Select-Object #{Name="Name";Expression={$_.Name}}, #{Name="Hash";Expression={$_.GetHashCode()}}, #{Name="FullName";Expression={$_.FullName}} |
Export-Csv -Path C:\Temp\testing.csv -NoTypeInformation -Append
}
The addition of the file hash will allow you to see if you have duplicates and the full name will allow you to see where they are located.
I am trying to use Rename-Item to remove trailing characters including the hyphen from a filename, ex. 123456.001.zip-4.22815.ren to 123456-001.zip.
Rename-Item -NewName ($_.Name.split('-')[0])
seems to be something I am missing after the split.
The split operation must be performed in a scriptblock ({}). A simple expression (()) won't work.
... | Rename-Item -NewName { $_.Name.Split('-')[0] }
Add -replace '^(\d+)\.', '$1-' if you want the period replaced with a hyphen.
... | Rename-Item -NewName { $_.Name.Split('-')[0] -replace '^(\d+)\.', '$1-' }
I got my script to work with these changes;
$src = "D:\temp"
Get-ChildItem -path $src -filter *.ren | ForEach-Object {
Rename-item -path $_.FullName -newname $_.Name.Split('-')[0] }