I have a script for extracting file metadata. I am trying to modify it so that it will skip a specified subfolder.
If you read the script, you can see there is a Param block, that includes options like "ExcludesFiles." I can get it to exclude a file, but I can't get it to exclude a folder.
Here is the script:
Function Get-FolderItem {
[cmdletbinding(DefaultParameterSetName='Filter')]
Param (
[parameter(Position=0,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
[Alias('FullName')]
[string[]]$Path = $PWD,
[parameter(ParameterSetName='Filter')]
[string[]]$Filter = '*.*',
[parameter(ParameterSetName='Exclude')]
[string[]]$ExcludeFile,
[parameter()]
[int]$MaxAge,
[parameter()]
[int]$MinAge
)
Begin {
$params = New-Object System.Collections.Arraylist
$params.AddRange(@("/L","/E","/NJH","/BYTES","/FP","/NC","/XJ","/R:0","/W:0","T:W","/UNILOG:c:\temp\test.txt"))
If ($PSBoundParameters['MaxAge']) {
$params.Add("/MaxAge:$MaxAge") | Out-Null
}
If ($PSBoundParameters['MinAge']) {
$params.Add("/MinAge:$MinAge") | Out-Null
}
}
Process {
ForEach ($item in $Path) {
Try {
$item = (Resolve-Path -LiteralPath $item -ErrorAction Stop).ProviderPath
If (-Not (Test-Path -LiteralPath $item -Type Container -ErrorAction Stop)) {
Write-Warning ("{0} is not a directory and will be skipped" -f $item)
Return
}
If ($PSBoundParameters['ExcludeFile']) {
$Script = "robocopy `"$item`" NULL $Filter $params /XF $($ExcludeFile -join ',')"
} Else {
$Script = "robocopy `"$item`" NULL $Filter $params"
}
Write-Verbose ("Scanning {0}" -f $item)
Invoke-Expression $Script | Out-Null
get-content "c:\temp\test.txt" | ForEach {
Try {
If ($_.Trim() -match "^(?<Children>\d+)\s(?<FullName>.*)") {
$object = New-Object PSObject -Property @{
FullName = $matches.FullName
#Extension = $matches.fullname -replace '.*\.(.*)','$1'
#FullPathLength = [int] $matches.FullName.Length
#FileHash = Get-FileHash -LiteralPath "\\?\$($matches.FullName)" |Select -Expand Hash
#Created = ([System.IO.FileInfo] $matches.FullName).creationtime
#Created = ([System.IO.FileInfo] "\\?\$($matches.FullName)").creationtime
#LastWriteTime = ([System.IO.FileInfo] "\\?\$($matches.FullName)").LastWriteTime
#Characters = (Get-Content -LiteralPath "\\?\$($matches.FullName)" | Measure-Object -ignorewhitespace -Character).Characters
#Size = ([System.IO.FileInfo] "\\?\$($matches.FullName)").length
#Access = ((Get-Acl -LiteralPath "\\?\$($matches.FullName)") |Select -Expand AccessToString)-replace '[\r\n]',' '
#$permission = (Get-Acl $Folder).Access | ?{$_.IdentityReference -match $User} | Select IdentityReference,FileSystemRights
#Owner = (Get-ACL $matches.Fullname).Owner
}
$object.pstypenames.insert(0,'System.IO.RobocopyDirectoryInfo')
Write-Output $object
} Else {
Write-Verbose ("Not matched: {0}" -f $_)
}
} Catch {
Write-Warning ("{0}" -f $_.Exception.Message)
Return
}
}
} Catch {
Write-Warning ("{0}" -f $_.Exception.Message)
Return
}
}
}
}
$a = Get-FolderItem "C:\Temp\ExtractMetadata" | Export-Csv -Path C:\Temp\2023-12-12Testing.csv -Encoding Unicode
I have tried the following, but the specified folder is not skipped:
$a = Get-FolderItem "C:\Temp\ExtractMetadata" -ExcludeFile "C:\Temp\ExtractMetadata\Folder_to_Skip\" | Export-Csv -Path C:\Temp\2023-12-12Testing.csv -Encoding Unicode
I also tried following, but the output file is blank:
$a = Get-FolderItem "C:\Temp\ExtractMetadata" -Filter "C:\Temp\ExtractMetadata\Folder to Skip\*.*" | Export-Csv -Path C:\Temp\2023-12-12Testing.csv -Encoding Unicode
I thought it might be based on Get Child Item (which has a built in excludes parameter) but I don't think this script uses Get-Child Item - it's just a loop. This answer indicates that what I need is a "continue" command, but where do I put it in? I'm unfamiliar with PowerShell syntax.
You need to implement the /XD
robocopy parameter. I found with using relative paths, what worked was to add them individually (multiple /XD,/XF entries.) There are several other improvements that could be made to this function.
Function Get-FolderItem {
[cmdletbinding(DefaultParameterSetName='Filter')]
Param (
[parameter(Position=0,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
[Alias('FullName')]
[string[]]$Path = $PWD,
[parameter()]
[string[]]$Filter = '*.*',
[parameter()]
[string[]]$ExcludeFile,
[parameter()]
[string[]]$ExcludeFolder,
[parameter()]
[int]$MaxAge,
[parameter()]
[int]$MinAge
)
Begin {
$params = New-Object System.Collections.Arraylist
$params.AddRange(@("/L","/E","/NJH","/BYTES","/FP","/NC","/XJ","/R:0","/W:0","T:W","/UNILOG:c:\temp\test.txt"))
If ($PSBoundParameters['MaxAge']) {
$params.Add("/MaxAge:$MaxAge") | Out-Null
}
If ($PSBoundParameters['MinAge']) {
$params.Add("/MinAge:$MinAge") | Out-Null
}
}
Process {
ForEach ($item in $Path) {
Try {
$item = (Resolve-Path -LiteralPath $item -ErrorAction Stop).ProviderPath
If (-Not (Test-Path -LiteralPath $item -Type Container -ErrorAction Stop)) {
Write-Warning ("{0} is not a directory and will be skipped" -f $item)
Return
}
If ($PSBoundParameters['ExcludeFile']) {
foreach($excluded in $ExcludeFile){
$params.Add("/XF `"$excluded`"") | Out-Null
}
}
If ($PSBoundParameters['ExcludeFolder']) {
foreach($excluded in $ExcludeFolder){
$params.Add("/XD `"$excluded`"") | Out-Null
}
}
$Script = "robocopy `"$item`" NULL $Filter $params"
Write-Verbose ("Scanning {0}" -f $item)
Invoke-Expression $Script | Out-Null
get-content "c:\temp\test.txt" | ForEach {
Try {
If ($_.Trim() -match "^(?<Children>\d+)\s(?<FullName>.*)") {
$object = New-Object PSObject -Property @{
FullName = $matches.FullName
#Extension = $matches.fullname -replace '.*\.(.*)','$1'
#FullPathLength = [int] $matches.FullName.Length
#FileHash = Get-FileHash -LiteralPath "\\?\$($matches.FullName)" |Select -Expand Hash
#Created = ([System.IO.FileInfo] $matches.FullName).creationtime
#Created = ([System.IO.FileInfo] "\\?\$($matches.FullName)").creationtime
#LastWriteTime = ([System.IO.FileInfo] "\\?\$($matches.FullName)").LastWriteTime
#Characters = (Get-Content -LiteralPath "\\?\$($matches.FullName)" | Measure-Object -ignorewhitespace -Character).Characters
#Size = ([System.IO.FileInfo] "\\?\$($matches.FullName)").length
#Access = ((Get-Acl -LiteralPath "\\?\$($matches.FullName)") |Select -Expand AccessToString)-replace '[\r\n]',' '
#$permission = (Get-Acl $Folder).Access | ?{$_.IdentityReference -match $User} | Select IdentityReference,FileSystemRights
#Owner = (Get-ACL $matches.Fullname).Owner
}
$object.pstypenames.insert(0,'System.IO.RobocopyDirectoryInfo')
Write-Output $object
} Else {
Write-Verbose ("Not matched: {0}" -f $_)
}
} Catch {
Write-Warning ("{0}" -f $_.Exception.Message)
Return
}
}
} Catch {
Write-Warning ("{0}" -f $_.Exception.Message)
Return
}
}
}
}