0

This is similar to the question Add folder name to beginning of filename but using PowerShell.

I have a directory structure as below:

Folder
  > SubFolder1
    > FileName1.abc
    > Filename2.abc
    > .............

> SubFolder2 > FileName11.abc > Filename12.abc > ..............

> ..........

etc. I want to rename the files inside the subfolders as:

SubFolder1_Filename1.abc
SubFolder1_Filename2.abc
SubFolder2_Filename11.abc
SubFolder2_Filename12.abc

i.e. add the folder name at the beginning of the file name with the delimiter "_".

I tried:

get-childitem -recurse | Rename-Item -NewName {$_.Directory.Name + "_" + $_.Name}

But what this does is changes the folder names to _SubFolder1, _SubFolder2, etc, and then changes the filenames to _SubFolder1_Filename1.abc, etc.

How do I ensure that the directory names remain unchanged but the filenames change?

Worthwelle
  • 4,816
Arnab
  • 103

2 Answers2

4

To ensure directory names remain unchanged use this:

get-childitem -recurse | 
  Where-Object {$_.Psiscontainer -eq $false} | 
    Rename-Item -NewName {$_.Directory.Name + "_" + $_.Name}

This will filter only the files.

wasif
  • 9,176
1

To extend what @Wasif_Hasan shows, know that Get-ChildItem has built-in switch parameters for a deal with Files and Folders, that one can capture to leverage in your use case.

So, this can be refactored. Here is a select example...

Get-ChildItem -Path 'D:\Temp' -File -Filter '*.txt' -Recurse | 
ForEach-Object{$($PSItem.Directory.BaseName + '_' +  $PSItem.Name)}

...but you could do the same thing with the Rename-Item cmdlet in that ForEach loop. For example:

Get-ChildItem -Path 'D:\Temp' -File -Filter '*.txt' -Recurse | 
ForEach-Object{
    $RenameItemSplat = @{
        Path    = $PSItem.FullName 
        NewName = $PSItem.Directory.BaseName + '_' + $PSItem.Name
        WhatIf  = $true
        Confirm = $true
    }
    Rename-Item @RenameItemSplat
}

Anytime you are doing destructive code, you should check results before final execution.

# Results
<#
What if: Performing the operation "Rename File" on target "Item: D:\Temp\abc.txt Destination: D:\Temp\Temp_abc.txt".
...
What if: Performing the operation "Rename File" on target "Item: D:\Temp\AddressFiles\File1.txt Destination: D:\Temp\AddressFiles\AddressFiles_File1.txt".
...
What if: Performing the operation "Rename File" on target "Item: D:\Temp\NewFolder\awél.txt Destination: D:\Temp\NewFolder\NewFolder_awél.txt".
...
What if: Performing the operation "Rename File" on target "Item: D:\Temp\Reference\awél.txt Destination: D:\Temp\Reference\Reference_awél.txt".
...
What if: Performing the operation "Rename File" on target "Item: D:\Temp\Source\awél.txt Destination: D:\Temp\Source\Source_awél.txt".
...
#>

PowerShell Help files:

Get-ChildItem -File 'D:\Temp' 
# Results
<#
    Directory: D:\Temp

Mode LastWriteTime Length Name


-a---- 25-May-20 15:44 25 abc.bat -a---- 20-May-20 11:40 94 abc.txt -a---- 10-Jan-20 17:59 0 awél.txt ... #>

Get-ChildItem -Directory 'D:\Temp'

Results

<# Directory: D:\Temp

Mode LastWriteTime Length Name


d----- 17-Feb-20 15:50 est
d----- 14-Mar-20 17:03 here
d----- 26-May-20 10:38 hold
... #>

Get specifics for a module, cmdlet, or function

(Get-Command -Name Get-ChildItem).Parameters (Get-Command -Name Get-ChildItem).Parameters.Keys

Results

<# ... Directory File ... #> Get-help -Name Get-ChildItem -Examples Get-help -Name Get-ChildItem -Full

Results

<# -Directory

To get a list of directories, use the Directory parameter or the Attributes parameter with the Directory property. You can use the Recurse parameter with Directory.

TABLE 3 Type: SwitchParameter Aliases: ad, d Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False

-File

To get a list of files, use the File parameter. You can use the Recurse parameter with File.

TABLE 5 Type: SwitchParameter Aliases: af Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False #> Get-help -Name Get-ChildItem -Online

postanote
  • 5,136