Exclude SubFolder in Get-ChildItem PowerShell Statement
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}
Christopher Cass
Updated on June 27, 2022Comments
-
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 about 7 yearsgc : 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.GetContentCommand
-
Christopher Cass about 7 yearsThat'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 about 7 yearsthere 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 about 7 yearsIt 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 about 7 yearswhat 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 about 7 yearsNothing 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 about 7 yearsAnd it is still doing what I want. Original errors are gone, now just showing error trying to hit folder outside of path.
-
Ricc Babbitt about 7 yearswith $path*.* but not with $path*.* ?
-
Christopher Cass about 7 yearssorry, 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 about 7 yearsI 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 about 7 yearsstill testing.. but one thing i had to do was (gc $_.fullname) or it was trying to look using the current path.