如何重命名目录名称,将名称字符串中每个单词的首字母替换为大写?

如何重命名目录名称,将名称字符串中每个单词的首字母替换为大写?

在 Windows 10 电脑上,我一直在使用 PFrank 工具和 Power Toys PowerRenamer 等免费实用程序。使用 PFrank,我能够将文件名中每个单词的大小写更改为大写,但它不会更改目录名称。

请问您知道 Powershell、CMD 或 BASH(使用 Windows 子系统 Linux)中的命令或脚本可以实现这一点吗?或者可以实现这一点的工具(最好是开源的)。由于我已经更改了文件名,因此我只想对目录名进行递归执行此操作。

谢谢。

答案1

从我的评论延伸一下。很简单。

更新

删除了原来的长答案并用以下内容替换以解决您的评论:

(Get-ChildItem -Path 'D:\Temp' -Directory -Recurse) -match 'src|dest' | 
ForEach-Object {
    "Proccessing $($PSItem.FullName) to TitleCase"
    $renameItemTempSplat = @{
        Path     = $PSitem.FullName
        NewName  = "$((Get-Culture).Textinfo.ToTitleCase($PSitem.Name.ToLower()))1"
        #WhatIf   = $true 
    }
    Rename-Item @renameItemTempSplat -PassThru | 
    Rename-Item -NewName $($((Get-Culture).Textinfo.ToTitleCase($PSitem.Name.ToLower())) -replace '1')
}
(Get-ChildItem -Path 'D:\Temp' -Directory -Recurse) -match 'src|dest'
# Results
<#
Proccessing D:\Temp\dest to TitleCase
Proccessing D:\Temp\Destination to TitleCase
Proccessing D:\Temp\src to TitleCase


    Directory: D:\Temp


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         12-Oct-20     14:27                Dest
d-----         24-Jan-21     22:24                Destination
d-----         12-Oct-20     13:27                Src
#>

关于 WhatIf/Confirm

答案2

您可以使用该Kernel32方法MoveFile来重命名文件和目录,而无需重命名两次。

以下代码使用新名称的相应属性(取决于类型)重命名文件和目录。

方法“MoveFile”实际上触发与使用Windows资源管理器以交互方式执行的相同过程。

# "MoveFile" works for files and folders

# only add type once
if ($null -eq ('Win32.Kernel32' -as [type])) {
    # add method 'MoveFile from' kernel32.dll
    # https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-movefile
    $signature = @'
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool MoveFile(string lpExistingFileName, string lpNewFileName);
'@
    Add-Type -MemberDefinition $signature -Name 'Kernel32' -Namespace Win32
}

$dirPath = 'C:\temp\CaseTest'
Get-ChildItem -LiteralPath $dirPath -Recurse -Directory | ForEach-Object {
    $parentPath = $currentName = $fileExtension = $null

    if ($_ -is [System.IO.DirectoryInfo]) {
        # Directories
        $parentPath  = $_.Parent.FullName
        $currentName = $_.Name

    } elseif ($_ -is [System.IO.FileInfo]) {
        # Files
        $parentPath    = $_.Directory.FullName
        $currentName   = $_.BaseName
        $fileExtension = $_.Extension
    }

    if ($null -notin $currentName, $parentPath) {
        $newName =  @(
            [cultureinfo]::CurrentCulture.TextInfo.ToTitleCase($currentName.ToLower()),
            $fileExtension
        ) -join ''

        $newPath    = Join-Path -Path $parentPath -ChildPath $newName
        $moveResult = [Win32.Kernel32]::MoveFile($_.FullName, $newPath)

        if (-not $moveResult) {
            # 'MoveFile' returns only $false in case of errors, 
            # so we have to build the respective exception.
            # This requires "SetLastError = true" in signature
            $win32Error     = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
            $win32Exception = [System.ComponentModel.Win32Exception]$win32Error
            Write-Error -Exception $win32Exception `
                -Message "$($win32Exception.Message) `"$($_.FullName)`""
        }
    }
}

相关内容