我正在使用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
在第二个目录中,我使用Get-ChildItem -Recurse
针对\\ store2 \ output执行脚本,它运行良好!但是,一旦我尝试对\\ 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 \ Output文件夹中运行。但是,当我针对\\ store \ logs进行启动时,它会尝试将\ ops \ scriptAlpha中的所有内容和\ ops \ scriptBeta中的所有内容移动到\ ops中的zip文件中,这不符合需要。我希望最终得到的是:
\\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,其中包含\ ops级别的WorkingFolder中的所有ScriptAlpha(及其文件夹/文件)和所有ScriptBeta(及其文件夹/文件)信息,并将它们压缩在一起。
我当时想做的是遍历根目录并将每个目录馈入一个数组,然后对数组中的每个项目进行操作,以查看其中是否有文件,是否有文件,然后做压缩文件。但是,我不知道这样做是否可行。我有点被困在精神上。
感谢您的帮助!对于它的价值,我已经搜索并搜索了SO,但我真的找不到任何东西。