Exclude SubFolder in Get-ChildItem PowerShell Statement

11,951

Solution 1

Not sure if there's a difference in PS version (I'm using 4) .. but there were a few tweaks i had to do to get it to work. This is how i did my test...

$oldhost = "RBABBITT1"
$oldip = "192.168.1.21"
$olddriveletter = "C"

$newhost = "RBABBITT2"
$newip = "192.168.1.22"
$newdriveletter = "D"


$path = "\\$newip\$newdriveletter$\test1"
$exclude = "$path\tools\*"
$files = get-childitem $path -Recurse | where-object{$_.fullname -notlike $exclude -and $_.PSIsContainer -eq $false}
$files | %{
    (gc $_.FullName) -replace $oldhost, $newhost -replace $oldip, $newip -replace [regex]::Escape("${olddriveletter}:\Website"), "${newDriveLetter}:\Website" | set-content $_.fullname
}

Solution 2

If you just run

get-childitem $path\*.* -recurse -exclude $exclude 

you should see that it's still returning the folder you are trying to exclude. This is because get-childitem -exclude doesn't work on containers.

Instead try

$files = get-childitem $path\*.* -recurse | where-object{$_.fullname -notlike $exclude}
Share:
11,951
Christopher Cass
Author by

Christopher Cass

Updated on June 27, 2022

Comments

  • Christopher Cass
    Christopher Cass almost 2 years

    I've been doing my best to get more familiar with PowerShell as a way to automate many of our regular tasks in an effort to eliminate human error. I support a web based application, and my current goal is to create a script to migrate the application from one server to another. So far I've gotten the script to install the application on the new server, copy the configuration files from the old server, and backup all the files prior to making any additional changes. The last thing I need to do is search through the configuration directory and all sub folders to replace all instances of the hostname, the IP address, and the directory location (in the event the drive letter changes on the new server) There is a folder called X:\Website\Tools\Database\Upgrade that contains a folder for every version that the customer has ever been on, and within that folder is the database upgrade script. I do not have permission to change anything in this folder, and frankly don't really care to change anything within X:\Website\tools.

    I have written this portion of the script as follows:

    #Replace all instances of hostname, IP address, and drive letter
    $path = "\\$newip\$newdriveletter$\Website"
    $exclude = @("$path\tools\*")
    $files = get-childitem $path\*.* -recurse -exclude $exclude 
    $files | %{
        (gc $_) -replace $oldhost, $newhost -replace $oldip, $newip -replace 
    "${olddriveletter}:\Website", "${newDriveLetter}:\Website" | set-content 
    $_.fullname
    }
    

    When I do this, it replaces everything I'm wanting it to replace, but it's still throwing the following error:

    gc : Access to the path 
    '\\10.5.17.60\E$\Website\Tools\Database\Upgrade\6.2.0' is denied.
    At C:\Folder\Powershell\Migrate.ps1:72 char:6
    +     (gc $_) -replace $oldhost, $newhost -replace $oldip, $newip -repl ...
    +      ~~~~~
         + CategoryInfo          : PermissionDenied: 
    (\\10.5.17.60\E$...e\Upgrade\6.2.0:String) [Get-Content], 
    UnauthorizedAccessException
        + FullyQualifiedErrorId : 
    

    I've also read that the -exclude parameter is pretty much broken in PowerShell and doesn't work well for excluding folders. The suggestion was to format it like so:

    #Replace all instances of hostname, IP address, and drive letter
    $path = "\\$newip\$newdriveletter$\Website"
    $files = get-childitem $path\*.* -recurse | select-object -expandproperty 
    fullname | where-object{$_ -notlike "\\tools\\"}
    $files | %{
    (gc $_) -replace $oldhost, $newhost -replace $oldip, $newip -replace "${olddriveletter}:\Website", "${newDriveLetter}:\Website" | set-content $_.fullname
    }
    

    Unfortunately, when I run this, I get the error:

    Set-Content : Cannot bind argument to parameter 'Path' because it is null.
    At C:\Folder\Powershell\Migrate.ps1:72 char:151
    + ... \WebAccess", "${newDriveLetter}:\Website" | set-content $_.fullname
    

    So basically I've achieved the end goal, but I'd really like to do this without any errors popping up. If people start running this and see red they're likely to freak out. So I'm thinking there has to be a way to exclude even looking into these folders. Possibly an If statement, but I'm not quite sure how to format that. Any suggestions?

  • Christopher Cass
    Christopher Cass about 7 years
    gc : Access to the path '\\10.5.17.60\E$\Backups\Website Backups\Website 6.3.1' is denied. At C:\Backups\Powershell\Migrate.ps1:72 char:6 + (gc $_) -replace $oldhost, $newhost -replace $oldip, $newip -repl ... + ~~~~~ + CategoryInfo : PermissionDenied: (\\10.5.17.60\E$...Website 6.3.1:String) [Get-Content], UnauthorizedAccessException + FullyQualifiedErrorId : GetContentReaderUnauthorizedAccessError,Microsoft.PowerShell‌​.Commands.GetContent‌​Command
  • Christopher Cass
    Christopher Cass about 7 years
    That's the error I'm seeing now... My $path variable is to \\10.5.17.60\E\Website. Any idea why it's trying to hit a folder that's not in that directory?
  • Ricc Babbitt
    Ricc Babbitt about 7 years
    there was supposed to be a "\" in there.. had a little trouble getting it to show up I'm assuming $newip = '10.5.17.60' and $newdriveletter = 'E'
  • Christopher Cass
    Christopher Cass about 7 years
    It seems to work without the \ and breaks with the \. Only issue is without the \ it seems to be trying to hit a folder that's not in the path. Path is \\10.5.17.60\E$\Website. Any idea why it's trying to hit \\10.5.17.60\Backups...? That's not in the $path...
  • Ricc Babbitt
    Ricc Babbitt about 7 years
    what are all you're variables set to? did you change any of the code in your original question? I understand it previously was doing what you wanted - only that it was hitting the \tools directory and giving you the error, correct? Is that still the case with your original code?
  • Christopher Cass
    Christopher Cass about 7 years
    Nothing has changed in the original code outside of replacing the line you suggested changing. and again, I've got the current code with $path*.* as the exclusions seemed to work that way, but not with $path*.*. $oldhost = "OLDHOSTNAME" $newhost = "NEWHOSTNAME" $oldip = "10.5.17.135" $newip = "10.5.17.60" $olddriveletter = "C" $newdriveletter = "E"
  • Christopher Cass
    Christopher Cass about 7 years
    And it is still doing what I want. Original errors are gone, now just showing error trying to hit folder outside of path.
  • Ricc Babbitt
    Ricc Babbitt about 7 years
    with $path*.* but not with $path*.* ?
  • Christopher Cass
    Christopher Cass about 7 years
    sorry, I missed the \ that time... it works with $path*.* but not $path*.* (there is a slash in the second one... same problem as you, it's not showing up...)
  • Christopher Cass
    Christopher Cass about 7 years
    I just edited it to include only .xml and .config files and it appears to be working without issue now. Thanks for the help!
  • Ricc Babbitt
    Ricc Babbitt about 7 years
    still testing.. but one thing i had to do was (gc $_.fullname) or it was trying to look using the current path.