Recurse работает с папками без файлов - нужно работать только с папками, содержащими файлы - PullRequest
0 голосов
/ 29 ноября 2018

Я работаю над сценарием PowerShell для архивирования старых журналов.Цель состоит в том, чтобы взять журналы старше X дней из всех других наших сценариев, событий, программного обеспечения и т. Д. (Которые записываются в центральное хранилище журналов) и заархивировать их для длительного хранения.Сценарий прекрасно работает, когда есть только один уровень вложенных папок, которые содержат файлы.Проблема в том, что он не работает хорошо, когда есть два (или более) слоя вложенных папок.

Вот пример структуры папок в центральном хранилище журналов:

\\store
└─logs
  ├─ops
  │ ├─ScriptAlpha
  │ │ ├─ScriptA-2018-10-17.log
  │ │ └─ScriptA-2018-10-10.log
  │ └─ScriptBeta
  │   ├─ScriptB-2018-11-17.log
  │   └─ScriptB-2018-11-09.log
  ├─Maintenance
  │ └─ScriptA
  │   ├─ScriptA-2018-10-22.log
  │   └─ScriptA-2018-10-26.log
  └─Ondemand
    └─ScriptBigly
      └─ScriptB-2018-11-27.log

У меня есть другой набор журналов, которые я создал сценарий для архивирования, и он прекрасно работает, но только когда нет многократных вложенных папок.Цель для этого выглядит следующим образом:

\\store2
└─Output
  ├─Alpha
  │ └─Alpha-2018-11-27.log
  ├─Bravo
  │ ├─Alpha-2018-11-27.log
  │ └─Alpha-2018-11-19.log
  ├─Charlie
  │ ├─Alpha-2018-11-27.log
  │ ├─Alpha-2018-11-18.log
  │ └─Alpha-2018-11-04.log
  └─Delta
    └─Alpha-2018-11-27.log

Во втором каталоге я выполняю сценарий для \\ store2 \ output с Get-ChildItem -Recurse, и он прекрасно работает!Однако, как только я пытаюсь сделать тот же сценарий для \\ store \ logs, он делает то, чего я не хочу.Я думаю, может быть, я не знаю, как правильно использовать -Recurse.

Первое, что я делаю со сценарием, это создаю PSDrives для корневой папки журналов (например, $sourcedrive = New-PSdrive -Name E -PSProvider FileSystem -Root \\\store\logs

Затем я запускаю цикл, чтобы перебрать и сжать содержимое.Вот цикл Foreach, но есть некоторые функции, которые я определяю в другом месте. Если мне нужно включить их, просто дайте мне знать, и я добавлю их, но это довольно длинный сценарий с включенными ими (всего 401 строка).

$Targets = (Get-ChildItem -Recurse -Path $SourceDrive | Where-Object { $_.PSIsContainer }).FullName
Write-Host "kicking off the foreach loop"
foreach ($Dir in $Targets) {
    Write-Host "Looking for relevant files"
    $Files = (Get-ChildItem -Recurse -Path $Dir -Exclude *.7z, *.zip | Where-Object { !$_.PSIsContainer -and $_.LastWriteTime -le (Get-Date).AddDays(-$Days)})
    Write-Host "$($Files.count) files older than $Days days found in $Dir" -ForegroundColor Green
    if ($files.Count -gt 0) {
        Write-Host "Compressing files in $dir" 
        Compress-Files $Files       #Moves the files into a working folder, then zips that folder
        Write-Host "Checking if zip created succesfully"
        if ($fileszipped = $true) {
            #Now that the files are all zipped, we can remove the source files, or not
            if ($nomove.IsPresent ) {
                Write-Host "Zip created! Removing working directories from $Dir and clearing out old files, not moving zip"
                Get-ChildItem -Recurse -Path $sourcedrive | Where-Object {
                    $_.PSIsContainer -and ($_.BaseName -like '*WorkingFiles*')
                } | Remove-Item -Recurse -Verbose
            } else {
                #If we didn't specify -nomove, then we can copy the zips, then remove the source files
                Write-Host "Zip created! Copying zip files now"
                $destin = (Join-Path -Path $LTSdrive -ChildPath (Split-Path $dir -Leaf))
                $ExitCode = Start-Robocopy -source $Dir -destin $destin -Verbose
                #Assuming robocopy was successful, let's remove our working directory and the files we've just zipped
                Write-Host "Checking if zip(s) copied succesfully"
                if (ParseRobocopyOutput $ExitCode){
                    Write-Host "Zip(s) copied! Removing working directories from $Dir and clearing out old files"
                    Get-ChildItem -Recurse -Path $sourcedrive | Where-Object {
                        $_.PSIsContainer -and ($_.BaseName -like '*WorkingFiles*')
                    } | Remove-Item -Recurse -Verbose
                }
            }
        }
    }
}

Для справки, вот «фактическая» часть функции Compress-Files:

$Path0 = $Path +"\WorkingFiles"
if ($Check -eq $false) {
    New-Item -Path $Path -ItemType Directory -Name WorkingFiles -Verbose
}

$i = 0
while ($i -lt $Files.Count) {
    $Path1 = $Path +"\"+ $Files[$i]
    Move-Item -Path $Path1 -Destination $Path0 -Verbose
    $i++
}

Когда я запускаю эту функцию, она работает так, как я хочу на\\ store2 \ Выходные папки. Но когда я запускаю его для \\ store \ logs, он пытается переместить все в \ ops \ scriptAlpha И все в \ ops \ scriptBeta в zip-файл в \ ops, который не подходитВ конце я хочу получить:

\\Archive
├─ops
│ ├─ScriptAlpha
│ │ └─ScriptA-archive-2018-11.7z
│ └─ScriptBeta
│   └─ScriptB-archive-2018-11.7z
├─Maintenance
│ ├─ScriptA
│ │ └─ScriptA-archive-2018-11.7z
│ └─ScriptBigly
│   └─ScriptB-archive-2018-11.7z
└─Output
  ├─Alpha
  │ └─Alpha-archive-2018-11.7z
  ├─Bravo
  │ └─Alpha-archive-2018-11.7z
  └─Charlie
    └─Alpha-archive-2018-11.7z

Вместо этого я получаю zip-архив, содержащий все ScriptAlpha (и его папки / файлы) и все ScriptBeta (и его папки)./ files) информация в WorkingFolder в файле \ opsВел, который застегивается на молнию все вместе.

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

Я ценю помощь!И что бы это ни стоило, я гуглил и искал ТАК, и я не могу ничего найти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...