Сценарий Powershell распечатывает повторяющиеся записи одного и того же пути - PullRequest
0 голосов
/ 24 апреля 2018

Моя цель - написать сценарий powershell, который будет рекурсивно проверять файловый сервер на наличие каталогов, которые "x" (вставляют дни) или старше.

Сначала я столкнулся с несколькими проблемами, и якажется, я получил большую часть этого решенного.Одна из проблем, с которыми я столкнулся, была с ограничением пути 248 символов.Я нашел пользовательскую функцию, которую я реализую в своем коде, чтобы обойти это ограничение.

В конечном итоге я хотел бы вывести путь и LastAccessTime папки и экспортировать информацию в легко читаемый CSV-файл.,

В настоящее время все работает правильно, но по некоторым причинам я получаю несколько путей, выводимых несколько раз (дубликаты, тройки, даже 4 раза).Я просто хочу, чтобы он выводился один раз для каждого каталога и подкаталога.

Буду признателен за любые рекомендации, которые я смогу получить.Заранее спасибо.Вот мой код

#Add the import and snapin in order to perform AD functions
Add-PSSnapin Quest.ActiveRoles.ADManagement -ea SilentlyContinue
Import-Module ActiveDirectory

#Clear Screen
CLS

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","/S","/NJH","/BYTES","/FP","/NC","/NFL","/TS","/XJ","/R:0","/W:0"))

        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 | ForEach {
                    Try 
                    {
                       If ($_.Trim() -match "^(?<Children>\d+)\s+(?<FullName>.*)") 
                       {
                            $object = New-Object PSObject -Property @{
                                ParentFolder = $matches.fullname -replace '(.*\\).*','$1'
                                FullName = $matches.FullName
                                Name = $matches.fullname -replace '.*\\(.*)','$1'
                            }
                            $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
            }
        }
    }
}

Function ExportFolders 
{
   #================ Global Variables ================

   #Path to folders
    $Dir = "\\myFileServer\somedir\blah"

   #Get all folders
    $ParentDir = Get-ChildItem $Dir | Where-Object {$_.PSIsContainer -eq $True}

   #Export file to our destination
    $ExportedFile = "c:\temp\dirFolders.csv"

   #Duration in Days+ the file hasn't triggered "LastAccessTime"
    $duration = 800
    $cutOffDate = (Get-Date).AddDays(-$duration)

   #Used to hold our information
    $results = @()

   #=============== Done with Variables ===============

    ForEach ($SubDir in $ParentDir)
    {
        $FolderPath = $SubDir.FullName

        $folders = Get-ChildItem -Recurse $FolderPath -force -directory| Where-Object { ($_.LastAccessTimeUtc -le $cutOffDate)} | Select-Object FullName, LastAccessTime

        ForEach ($folder in $folders)
        {
            $folderPath = $folder.fullname
            $fixedFolderPaths = ($folderPath | Get-FolderItem).fullname

            ForEach ($fixedFolderPath in $fixedFolderPaths)
            {
                #$fixedFolderPath
                $getLastAccessTime = $(Get-Item $fixedFolderPath -force).lastaccesstime
                #$getLastAccessTime

                $details = @{ "Folder Path" = $fixedFolderPath; "LastAccessTime" = $getLastAccessTime}

                $results += New-Object PSObject -Property $details
                $results
            }               
        }
    }
}

ExportFolders

Я немного обновил свой код и упростил его.Вот новый код.

#Add the import and snapin in order to perform AD functions
Add-PSSnapin Quest.ActiveRoles.ADManagement -ea SilentlyContinue
Import-Module ActiveDirectory

#Clear Screen
CLS

Function ExportFolders 
{
   #================ Global Variables ================

   #Path to user profiles in Barrington
    $Dir = "\\myFileServer\somedir\blah"

   #Get all user folders
    $ParentDir = Get-ChildItem $Dir | Where-Object {$_.PSIsContainer -eq $True} | where {$_.GetFileSystemInfos().Count -eq 0 -or $_.GetFileSystemInfos().Count -gt 0}

   #Export file to our destination
    $ExportedFile = "c:\temp\dirFolders.csv"

   #Duration in Days+ the file hasn't triggered "LastAccessTime"
    $duration = 1
    $cutOffDate = (Get-Date).AddDays(-$duration)

   #Used to hold our information
    $results = @()
    $details = $null

   #=============== Done with Variables ===============

    ForEach ($SubDir in $ParentDir)
    {
        $FolderName = $SubDir.FullName
        $FolderInfo = $(Get-Item $FolderName -force) | Select-Object FullName, LastAccessTime #| ft -HideTableHeaders
        $FolderLeafs = gci -Recurse $FolderName -force -directory | Where-Object {$_.PSIsContainer -eq $True} | where {$_.GetFileSystemInfos().Count -eq 0 -or $_.GetFileSystemInfos().Count -gt 0} | Select-Object FullName, LastAccessTime #| ft -HideTableHeaders

        $details = @{ "LastAccessTime" = $FolderInfo.LastAccessTime; "Folder Path" = $FolderInfo.FullName}
        $results += New-Object PSObject -Property $details

        ForEach ($FolderLeaf in $FolderLeafs.fullname)
        {
            $details = @{ "LastAccessTime" = $(Get-Item $FolderLeaf -force).LastAccessTime; "Folder Path" = $FolderLeaf}
            $results += New-Object PSObject -Property $details
        }

        $results
    }
}

ExportFolders

Переменная FolderInfo иногда печатается несколько раз, но переменная FolderLeaf печатает один раз из того, что я вижу.Проблема заключается в том, что если я переместлю или удалю переменную результатов из данных, которые распечатывают folderInfo, то родительские каталоги не будут распечатаны.Только все вложенные папки показаны.Также некоторые каталоги пусты и не распечатываются, и я хочу распечатать все каталоги, включая пустые.

Обновленный код, кажется, печатает все каталоги нормально, но, как я уже говорил, я все еще получаю несколько дубликатов переменных $ FolderInfo.

Я думаю, что мне нужно поставить условие или что-то, чтобы проверить, еслион уже обработан, но я не уверен, какое условие я бы использовал для этого, чтобы он не распечатывался несколько раз.

1 Ответ

0 голосов
/ 24 апреля 2018

В вашем ExportFolders вы Get-ChildItem -Recurse, а затем перебираете все подпапки, вызывая Get-FolderItem. Затем в Get-FolderItem вы предоставляете Robocopy с флагом /S в $params.AddRange(@("/L", "/S", "/NJH", "/BYTES", "/FP", "/NC", "/NFL", "/TS", "/XJ", "/R:0", "/W:0")) Флаг /S, означающий копировать подкаталоги, но не пустые. Таким образом, вы возвращаетесь снова. Скорее всего, вам просто нужно убрать флаг /S, чтобы вы выполняли всю свою рекурсию в ExportFolders.

В ответ на редактирование:

Ваш $results находится внутри цикла. Таким образом, у вас будет n дубликатов для первого $subdir, затем n-1 дубликатов для второго и т. Д.

ForEach ($SubDir in $ParentDir) {
    #skipped code
    ForEach ($FolderLeaf in $FolderLeafs.fullname) {
         #skipped code
    }
    $results
}

должно быть

ForEach ($SubDir in $ParentDir) {
    #skipped code
    ForEach ($FolderLeaf in $FolderLeafs.fullname) {
         #skipped code
    }
}
$results
...