简体   繁体   中英

How to rename files and subfolders including subfolders which are renamed in powershell?

I have this powershell code which goes through a folder and creates a list of all files and subfolders in the folder and renames them for me (replacing spaces with underscores). The code both works and doesn't work:

$myFiles = Get-ChildItem -Path "\\folder path" -include "* *" -recurse
foreach ($file in $myFiles)
{
    $newFileName=$file.Name.Replace(" ","_")
    Rename-Item $file $newFileName
}

The code successfully renames all the subfolders and files in the original folder, but then it looks for the subfolder which no longer exists (because the spaces were changed to dashes), and creates the Get-ChildItem: Cannot find path '\\folder path' because it does not exist. error.

This code will work if I run it multiple times, until I stop getting errors. Each time I run it, it goes one subfolder level deeper until there are no more subfolders to rename. So, I get the desired result in the end, but is there a way to make this code work by starting with the lowest nested files, or any other method not requiring me to run the same code multiple times?

A Stack ( last-in-first-out ) should work for this case. I added a -WhatIf switch to Rename-Item so you can confirm that the code is doing what you feel is right, you may remove it after confirmation.

using namespace System.IO
using namespace System.Collections.Generic

$stack = [Stack[string]]::new()
$path = "\\folder path"

foreach($folder in [Directory]::EnumerateDirectories($path, '*', [SearchOption]::AllDirectories))
{
    $stack.Push($folder)
    foreach($file in [Directory]::EnumerateFiles($folder))
    {
        $stack.Push($file)
    }
}

while($stack.Count)
{
    [FileInfo]$item = $stack.Pop()
    if(-not $item.Name.Contains(' ')) { continue }
    $newFileName = $item.Name.Replace(' ','_')
    Rename-Item -LiteralPath $item.FullName -NewName $newFileName -WhatIf
}

Here is how I thought of doing it. I iterated through all files first because there is no folder dependencies to rename those. Then I iterated through all folders and put the folders in reverse and renamed them all. Seems to work.

$myFiles = Get-ChildItem -Path 'E:\Data\test folder' -include "* *" -recurse | Where {$_.PSIsContainer -eq $false}
$myFiles
foreach ($file in $myFiles)
{
    $newFileName=$file.Name.Replace(" ","_")
    Rename-Item $file $newFileName
}
Get-ChildItem -Path 'E:\Data\test folder' -recurse

$myfolders = Get-ChildItem -Path 'E:\Data\test folder' -include "* *" -recurse | Where {$_.PSIsContainer -eq $True} | Sort-Object -Descending
$myfolders.FullName
foreach ($folder in $myfolders)
{
    $newFolderName=$folder.Name.Replace(" ","_")
    Rename-Item $folder $newFolderName
}
Get-ChildItem -Path 'E:\Data\test folder' -recurse -directory

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM