Search code examples
powershellpowershell-5.0

Skipping files with a given prefix when renaming


I have the following script for renaming a bunch of files in a directory, adding the name of the directory to the start of them:

$s = "Y:\Teknisk Arkiv\Likeretter 111-Å1\E2_Kretsskjema\02_Likeretter styring\3AJJ000302-222"

Get-ChildItem -Path $s -Exclude $_.Directory.Name* | rename-item -NewName { $_.Directory.Name + '_' + $_.Name }

Before running the script the files in the folder looks something like this

enter image description here

after like this

enter image description here

As you can see it does more or less what I want, except that -exclude $_.DirectoryName* doesn't prevent files which already have the foldername as a prefix from being renamed. What am I doing wrong here?


Solution

    • $_ in a pipeline is only defined inside a script block used in a non-initial pipeline segment, where it refers to the input object at hand, so in your Get-ChildItem command it is effectively undefined.

      • Even if $_.Directory.Name did have a value, $_.Directory.Name* wouldn't work as expected, because it would be passed as 2 arguments (you'd have to use "$($_.Directory.Name)*" or ($_.Directory.Name + '*').

      • You instead want to extract the directory name from the $s input path, which you can do with Split-Path -Leaf, and then append '*'.

    • In order for -Exclude to be effective, the input path must end in \*, because -Include and -Exclude filters - perhaps surprisingly - operate on the leaf component of the -Path argument, not on the child paths (unless -Recurse is also specified).

    To put it all together:

    Get-Item -Path $s\* -Exclude ((Split-Path -Leaf $s) + '*') | 
      Rename-Item -NewName { $_.Directory.Name + '_' + $_.Name }
    

    I've switched to Get-Item, since \* is now being used to enumerate the children, but Get-ChildItem would work too.