首页 > 解决方案 > 为多个文件夹中的所有文件添加前缀

问题描述

我有几个文件夹(准确地说是 35 个),每个文件夹包含 10-12 个子文件夹,每个子文件夹大约 20 个文件。

我想在每个文件前面加上子文件夹的名称,但我发现的唯一命令是一次只重命名一个文件夹:

dir | Rename-Item -NewName {$_.Directory.Name + " - " + $_.Name}

有没有办法遍历所有文件夹?(我不习惯Powershell)

标签: windowspowershellshell

解决方案


是的,有,并且在 PowerShell 帮助文件中有详细说明。这就是 -recurse 参数的用途。

# Get specifics for a module, cmdlet, or function
(Get-Command -Name Get-ChildItem).Parameters
(Get-Command -Name Get-ChildItem).Parameters.Keys|clip
# Results
<#
Path
LiteralPath
Filter
Include
Exclude
Recurse
Depth
Force
Name
Verbose
Debug
ErrorAction
WarningAction
InformationAction
ErrorVariable
WarningVariable
InformationVariable
OutVariable
OutBuffer
PipelineVariable
UseTransaction
Attributes
Directory
File
Hidden
ReadOnly
System
#>

Get-help -Name Get-ChildItem -Examples
# Results
<#
Get-ChildItem
Get-Childitem -System -File -Recurse
Get-ChildItem -Attributes !Directory,!Directory+Hidden
dir -att !d,!d+h
dir -ad
Get-ChildItem -File -Attributes !ReadOnly -path C:\ps-test
get-childitem . -include *.txt -recurse -force
get-childitem c:\windows\logs\* -include *.txt -exclude A*
get-childitem -name

#>
Get-help -Name Get-ChildItem -Full
Get-help -Name Get-ChildItem -Online


(Get-Command -NameR ename-Item).Parameters
(Get-Command -Name Rename-Item).Parameters.Keys|clip
# Results
<#
Path
LiteralPath
NewName
Force
PassThru
Credential
Verbose
Debug
ErrorAction
WarningAction
InformationAction
ErrorVariable
WarningVariable
InformationVariable
OutVariable
OutBuffer
PipelineVariable
WhatIf
Confirm
UseTransaction
#>

Get-help -Name Rename-Item -Examples
# Results
<#
Rename-Item -Path "c:\logfiles\daily_file.txt" -NewName "monday_file.txt"
Rename-Item -Path "project.txt" -NewName "d:\archive\old-project.txt"
Move-Item -Path "project.txt" -Destination "d:\archive\old-project.txt"
Rename-Item -Path "HKLM:\Software\MyCompany\Advertising" -NewName "Marketing"
Get-ChildItem *.txt | Rename-Item -NewName { $_.name -Replace '\.txt','.log' }
#>
Get-help -Name Rename-Item -Full
Get-help -Name Rename-Item -Online

然而,您在代码中所做的只是重命名目录,而不是该目录或子目录中的文件。您还没有指定和启动目录,因此它将对您当前所在的任何目录与您可能想要的目录执行操作。

您需要循环所有导向器并循环这些目录中的所有文件,以重命名目录中传递的文件。

根据我的“-WhatIf”评论更新

只是另一种做'marzse'给你的方式,只需通知正在处理的内容,并进行检查。如果情况看起来不错,请删除 -Whatif,然后再次运行它。如果您不确定它在做什么,或者您愿意接受这样做的后果,请不要破坏任何人的代码。

Clear-Host
Get-ChildItem -Directory | 
ForEach-Object {
    "`n *** Working on resource named: $($PSItem.BaseName) *** `n"
    $DirName = $($PSItem.BaseName)

    Get-ChildItem -Path $DirName -File | 
    ForEach{
        $PSItem.FullName | 
        Rename-Item -NewName "$($DirName)_$($PSItem)" -WhatIf
    } 
}
# Results test the rename process 
<#
*** Working on resource named: AddressFiles *** 

What if: Performing the operation "Rename File" on target "Item: D:\temp1\AddressFiles\(MSINFO32) command-line tool switches.pdf Destination: D:\temp1\AddressFiles\AddressFiles_(MSINFO32) command-line tool switches.pdf".
What if: Performing the operation "Rename File" on target "Item: D:\temp1\AddressFiles\File1.txt Destination: D:\temp1\AddressFiles\AddressFiles_File1.txt".
What if: Performing the operation "Rename File" on target "Item: D:\temp1\AddressFiles\File2.txt Destination: D:\temp1\AddressFiles\AddressFiles_File2.txt".

 *** Working on resource named: ChildFolder *** 

What if: Performing the operation "Rename File" on target "Item: D:\temp1\ChildFolder\5 Free Software You'll Wish You Knew Earlier! 2019 - YouTube.url Destination: D:\temp1\ChildFolder\ChildFolder_5 Free Software You'll Wish You Knew Earlier! 2019 - YouTube.url".
What if: Performing the operation "Rename File" on target "Item: D:\temp1\ChildFolder\awél.txt Destination: D:\temp1\ChildFolder\ChildFolder_awél.txt".
What if: Performing the operation "Rename File" on target "Item: D:\temp1\ChildFolder\hello.bat Destination: D:\temp1\ChildFolder\ChildFolder_hello.bat".
....

 *** Working on resource named: dest *** 

What if: Performing the operation "Rename File" on target "Item: D:\temp1\dest\mytest - 2019.txt Destination: D:\temp1\dest\dest_mytest - 2019.txt".
What if: Performing the operation "Rename File" on target "Item: D:\temp1\dest\mytest.txt Destination: D:\temp1\dest\dest_mytest.txt".
#>

永远不要急于编写代码或一次完成所有事情。一步一步地介入,以确保您在每一步都得到了您所期望的。

为了达到上述目的,这就是我的意思。逻辑完整的步骤,然后一旦你理解了你就可以优化 marsze 显示的内容。

Push-Location -Path 'D:\Temp1'
Get-Location
# Results
<#
Path    
----    
D:\temp1
#>

Get-ChildItem 
# Results all file in the root
<#
    Directory: D:\temp1


Mode                 LastWriteTime         Length Name                                                                                                       
----                 -------------         ------ ----                                                                                                       
d-----         01-Nov-20     23:43                AddressFiles                                                                                               
d-----         01-Nov-20     23:43                BonoboGitServer                                                                                            
d-----         01-Nov-20     23:44                ChildFolder
...
#>

Get-ChildItem -Recurse 
# Results all folder and file in root and sub-direcotries
<#
    Directory: D:\temp1


Mode                 LastWriteTime         Length Name                                                                                                       
----                 -------------         ------ ----                                                                                                       
d-----         01-Nov-20     23:43                AddressFiles                                                                                               
d-----         01-Nov-20     23:43                BonoboGitServer                                                                                            
d-----         01-Nov-20     23:44                ChildFolder 
...
    Directory: D:\temp1\AddressFiles


Mode                 LastWriteTime         Length Name                                                                                                       
----                 -------------         ------ ----                                                                                                       
-a----         06-Aug-16     18:25         406508 (MSINFO32) command-line tool switches.pdf                                                                  
-a----         19-Mar-20     19:57            156 File1.txt                                                                                                  
-a----         19-Mar-20     19:57            150 File2.txt 
...
#>

Get-ChildItem -Directory
# Results get only directory names
<#
    Directory: D:\temp1


Mode                 LastWriteTime         Length Name                                                                                                       
----                 -------------         ------ ----                                                                                                       
d-----         01-Nov-20     23:43                AddressFiles                                                                                               
d-----         01-Nov-20     23:43                BonoboGitServer                                                                                            
d-----         01-Nov-20     23:44                ChildFolder
...
#>

Get-ChildItem -Directory | 
ForEach-Object {
    Get-ChildItem -Path $PSItem.Name -Recurse | 
    Select-Object -Property Fullname
}
# Results use directory name to get all files in that directory tree
<#
FullName                                                                                                                     
--------                                                                                                                     
D:\temp1\AddressFiles\(MSINFO32) command-line tool switches.pdf                                                              
D:\temp1\AddressFiles\File1.txt                                                                                              
D:\temp1\AddressFiles\File2.txt
...
#>

Get-ChildItem -Directory | 
ForEach-Object {
    "`n *** Working on resource named: $($PSItem.BaseName) *** `n"
    ($DirName = $($PSItem.BaseName))
}
# Results
<#
 *** Working on resource named: AddressFiles *** 

AddressFiles

 *** Working on resource named: BonoboGitServer *** 

ChildFolder

 *** Working on resource named: dest *** 
...
#>

Get-ChildItem -Directory | 
ForEach-Object {
    "`n *** Working on resource named: $($PSItem.BaseName) *** `n"
    $DirName = $($PSItem.BaseName)

    Get-ChildItem -Path $DirName -File 
}
# Results
<#
 *** Working on resource named: AddressFiles *** 



    Directory: D:\temp1\AddressFiles


Mode                 LastWriteTime         Length Name                                                                                                       
----                 -------------         ------ ----                                                                                                       
-a----         06-Aug-16     18:25         406508 (MSINFO32) command-line tool switches.pdf                                                                  
-a----         19-Mar-20     19:57            156 File1.txt                                                                                                  
-a----         19-Mar-20     19:57            150 File2.txt                                                                                                  

 *** Working on resource named: BonoboGitServer *** 


 *** Working on resource named: ChildFolder *** 



    Directory: D:\temp1\ChildFolder


Mode                 LastWriteTime         Length Name                                                                                                       
----                 -------------         ------ ----                                                                                                       
-a----         29-Dec-19     21:50             69 5 Free Software You'll Wish You Knew Earlier! 2019 - YouTube.url                                           
-a----         10-Jan-20     17:59              0 awél.txt                                                                                                   
-a----         04-Jan-20     02:01             39 hello.bat 
#>

Get-ChildItem -Directory | 
ForEach-Object {
    "`n *** Working on resource named: $($PSItem.BaseName) *** `n"
    $DirName = $($PSItem.BaseName)

    Get-ChildItem -Path $DirName -File | 
    ForEach{
        $PSItem.FullName
    } 
}
# Results
<#
 *** Working on resource named: AddressFiles *** 

D:\temp1\AddressFiles\(MSINFO32) command-line tool switches.pdf
D:\temp1\AddressFiles\File1.txt
D:\temp1\AddressFiles\File2.txt

 *** Working on resource named: BonoboGitServer *** 


 *** Working on resource named: ChildFolder *** 

D:\temp1\ChildFolder\5 Free Software You'll Wish You Knew Earlier! 2019 - YouTube.url
D:\temp1\ChildFolder\awél.txt
D:\temp1\ChildFolder\hello.bat
...
#>

推荐阅读