尝试遍历文件夹并对每个文件执行递归操作
Trying to iterate through folders and take recursive actions on each file
我正在尝试构建一个脚本,用于根据上次访问日期删除旧文件。作为脚本的一部分,我想询问每个子文件夹,查找最近 X 天未访问的文件,在找到的文件的同一文件夹中创建一个日志,并在日志中记录文件详细信息,然后删除文件。
我认为我需要的是一个嵌套循环,循环 1 将获取每个子文件夹 (Get-ChildItem -Directory -Recurse
),然后对于找到的每个文件夹,第二个循环检查所有文件的上次访问日期,如果超出限制将追加文件夹中日志文件的文件详细信息(供用户参考)以及主日志文件(供 IT 管理员使用)
循环 1 按预期工作并获取子文件夹,但我无法让内部循环递归遍历文件夹中的对象,我正在尝试在第一个循环中使用 Get-ChildItem
,是吗正确的做法?
下面的代码示例,我添加了伪代码来演示逻辑,它确实是我需要帮助的循环:
# Set variables
$FolderPath = "E:TEST_G"
$ArchiveLimit = 7
$ArchiveDate = (Get-Date).AddDays(-$ArchiveLimit)
$MasterLogFile = "C:\Temp\ArchiveLog $(Get-Date -f yyyy-MM-dd).csv"
# Loop 1 - Iterate through each subfolder of $FolderPath
Get-ChildItem -Path $FolderPath -Directory -Recurse | ForEach-Object {
# Loop 2 - Check each file in the Subfolder and if Last Access is past
# $ArchiveDate take Action
Get-ChildItem -Path $_.DirectoryName | where {
$_.LastAccessTime -le $ArchiveDate
} | ForEach-Object {
# Check if FolderLogFile Exists, if not create it
# Append file details to folder Log
# Append File & Folder Details to Master Log
}
}
我觉得你有点过于复杂了:
#Set Variables
$FolderPath = "E:\TEST_G"
$ArchiveLimit = 7
$ArchiveDate = (Get-Date).AddDays(-$ArchiveLimit)
$MasterLogFile = "C:\Temp\ArchiveLog $(get-date -f yyyy-MM-dd).csv"
If (!(Test-Path $MasterLogFile)) {New-Item $MasterLogFile -Force}
Get-ChildItem -Path $FolderPath -File -Recurse |
Where-Object { $_.LastAccessTime -lt $ArchiveDate -and
$_.Extension -ne '.log' } |
ForEach-Object {
$FolderLogFile = Join-Path $_.DirectoryName 'name.log'
Add-Content -Value "details" -Path $FolderLogFile,$MasterLogFile
Try {
Remove-Item $_ -Force -EA Stop
} Catch {
Add-Content -Value "Unable to delete item! [$($_.Exception.GetType().FullName)] $($_.Exception.Message)"`
-Path $FolderLogFile,$MasterLogFile
}
}
编辑:
多个递归循环是不必要的,因为您已经在管道中执行了递归操作。它功能强大,无需采取额外操作即可进行处理。另一个答案中的 Add-Content
也是比 Out-File
更好的解决方案,所以我替换了我的。
请注意,Add-Content
的 -Force
标志不会像 New-Item
那样创建文件夹结构。这就是 $MasterLogFile
声明下的行的原因。
您的嵌套循环不需要递归(外层循环已经解决了)。只需处理每个文件夹中的文件(确保排除文件夹日志):
Get-ChildItem -Path $FolderPath -Directory -Recurse | ForEach-Object {
$FolderLogFile = Join-Path $_.DirectoryName 'FolderLog.log'
Get-ChildItem -Path $_.DirectoryName -File | Where-Object {
$_.LastAccessTime -le $ArchiveDate -and
$_.FullName -ne $FolderLogFile
} | ForEach-Object {
'file details' | Add-Content $FolderLogFile
'file and folder details' | Add-Content $MasterLogFile
Remove-Item $_.FullName -Force
}
}
您不需要测试文件夹日志文件是否存在,因为如果缺少,Add-Content
将自动创建它。
我正在尝试构建一个脚本,用于根据上次访问日期删除旧文件。作为脚本的一部分,我想询问每个子文件夹,查找最近 X 天未访问的文件,在找到的文件的同一文件夹中创建一个日志,并在日志中记录文件详细信息,然后删除文件。
我认为我需要的是一个嵌套循环,循环 1 将获取每个子文件夹 (Get-ChildItem -Directory -Recurse
),然后对于找到的每个文件夹,第二个循环检查所有文件的上次访问日期,如果超出限制将追加文件夹中日志文件的文件详细信息(供用户参考)以及主日志文件(供 IT 管理员使用)
循环 1 按预期工作并获取子文件夹,但我无法让内部循环递归遍历文件夹中的对象,我正在尝试在第一个循环中使用 Get-ChildItem
,是吗正确的做法?
下面的代码示例,我添加了伪代码来演示逻辑,它确实是我需要帮助的循环:
# Set variables
$FolderPath = "E:TEST_G"
$ArchiveLimit = 7
$ArchiveDate = (Get-Date).AddDays(-$ArchiveLimit)
$MasterLogFile = "C:\Temp\ArchiveLog $(Get-Date -f yyyy-MM-dd).csv"
# Loop 1 - Iterate through each subfolder of $FolderPath
Get-ChildItem -Path $FolderPath -Directory -Recurse | ForEach-Object {
# Loop 2 - Check each file in the Subfolder and if Last Access is past
# $ArchiveDate take Action
Get-ChildItem -Path $_.DirectoryName | where {
$_.LastAccessTime -le $ArchiveDate
} | ForEach-Object {
# Check if FolderLogFile Exists, if not create it
# Append file details to folder Log
# Append File & Folder Details to Master Log
}
}
我觉得你有点过于复杂了:
#Set Variables
$FolderPath = "E:\TEST_G"
$ArchiveLimit = 7
$ArchiveDate = (Get-Date).AddDays(-$ArchiveLimit)
$MasterLogFile = "C:\Temp\ArchiveLog $(get-date -f yyyy-MM-dd).csv"
If (!(Test-Path $MasterLogFile)) {New-Item $MasterLogFile -Force}
Get-ChildItem -Path $FolderPath -File -Recurse |
Where-Object { $_.LastAccessTime -lt $ArchiveDate -and
$_.Extension -ne '.log' } |
ForEach-Object {
$FolderLogFile = Join-Path $_.DirectoryName 'name.log'
Add-Content -Value "details" -Path $FolderLogFile,$MasterLogFile
Try {
Remove-Item $_ -Force -EA Stop
} Catch {
Add-Content -Value "Unable to delete item! [$($_.Exception.GetType().FullName)] $($_.Exception.Message)"`
-Path $FolderLogFile,$MasterLogFile
}
}
编辑:
多个递归循环是不必要的,因为您已经在管道中执行了递归操作。它功能强大,无需采取额外操作即可进行处理。另一个答案中的 Add-Content
也是比 Out-File
更好的解决方案,所以我替换了我的。
请注意,Add-Content
的 -Force
标志不会像 New-Item
那样创建文件夹结构。这就是 $MasterLogFile
声明下的行的原因。
您的嵌套循环不需要递归(外层循环已经解决了)。只需处理每个文件夹中的文件(确保排除文件夹日志):
Get-ChildItem -Path $FolderPath -Directory -Recurse | ForEach-Object {
$FolderLogFile = Join-Path $_.DirectoryName 'FolderLog.log'
Get-ChildItem -Path $_.DirectoryName -File | Where-Object {
$_.LastAccessTime -le $ArchiveDate -and
$_.FullName -ne $FolderLogFile
} | ForEach-Object {
'file details' | Add-Content $FolderLogFile
'file and folder details' | Add-Content $MasterLogFile
Remove-Item $_.FullName -Force
}
}
您不需要测试文件夹日志文件是否存在,因为如果缺少,Add-Content
将自动创建它。