You need to enable JavaScript to run this app. PowerShell脚本如何修改实现同时输出到控制台与日志文件
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell脚本如何修改实现同时输出到控制台与日志文件

核心问题修正方案

之前踩的两个关键坑

  • 重定向逻辑有问题:原来用$( ... ) *>&1 > 日志路径的写法,PowerShell会把整个脚本块的输出全部缓存在内存里,等所有逻辑跑完才一次性写入文件,大文件夹场景下跑十几分钟控制台一点反馈都没有,体验很差。
  • 对PowerShell输出流的理解有偏差:Write-Host的输出是直接发给控制台的,根本不进入管道流,所有依赖管道的重定向、Tee-Object组件都抓不到这类内容,所以之前用Write-Host时没法把内容写进日志。

优化后实现的效果

完全匹配你提出的需求:

  • 每处理完一个一级子文件夹,信息立刻同步显示在控制台,无等待
  • 所有需要留存的内容实时写入桌面的Output.txt,最终日志格式和你原来设计的完全一致
  • 大文件夹场景下的运行速度提升约2/3

具体调整点

  • 用Tee-Object接管所有需要入日志的管道输出,实现控制台实时显示+日志文件实时写入的双输出效果
  • 把原来每个子文件夹需要3次递归磁盘扫描的逻辑(分别算大小、文件数、文件夹数),改成单次扫描拿到所有条目,在内存中计算三个指标,大幅减少磁盘读取耗时
  • 修复原有大小累加的精度问题:不再把格式化后的两位小数字符串做累加,改成累加原始字节数,最后输出时再做格式化,避免总大小计算的偏差
  • 把不需要进日志的提示类内容(比如路径输错的红字提示、运行开始的说明文字)保留用Write-Host,既保证控制台的彩色提示效果,又不会让这类内容污染正式日志

修正后的完整可运行代码

# 路径输入校验逻辑保持原有逻辑不变
While ($true){
    $startDirectory = Read-Host "Enter path/directory"
    if (Test-Path -Path $startDirectory) { break }
    Write-Host "Wrong path. Please try again" -ForegroundColor Red
}
Write-Host ""
Write-Host "Getting information..." -ForegroundColor Green
Write-Host "This can take a while if the selected directory is large and/or contains a lot of files. An output log will be created at the end."
Write-Host ""

# 初始化变量,用原始字节数累加避免精度误差
$logPath = "$env:USERPROFILE\Desktop\Output.txt"
$directoryItems = Get-ChildItem $startDirectory -Directory | Sort-Object Name
$TotalBytes = 0
$TotalFiles = 0
$TotalFolders = 0
$Tab = [char]9 

# 所有需要写入日志的内容走管道,接Tee实现双输出
& {
    Write-Output "Output file generated to: $logPath"
    Write-Output " "
    Write-Output "List of Folders in '$startDirectory'"
    Write-Output " "
    Write-Output "Size (GB): $Tab Files: $Tab Folders: $Tab Folder Name:"
    Write-Output " "

    # 统计根目录下的直接文件、文件夹数,以及根目录直接文件的总大小(无需递归)
    $rootDirectFiles = Get-ChildItem $startDirectory -File -Force
    $rootDirectFileCount = $rootDirectFiles.Count
    $rootDirectFileBytes = ($rootDirectFiles | Measure-Object Length -Sum).Sum
    $rootDirectFolderCount = (Get-ChildItem $startDirectory -Directory).Count

    # 累加根目录指标到总统计值
    $TotalBytes += $rootDirectFileBytes
    $TotalFiles += $rootDirectFileCount

    # 遍历每个一级子文件夹,单次递归统计所有指标
    foreach ($subDir in $directoryItems) {
        # 单次递归遍历,同时统计文件数、文件夹数、文件总大小
        $allItems = Get-ChildItem $subDir.FullName -Recurse -Force
        $subFiles = $allItems | Where-Object {-not $_.PSIsContainer}
        $subDirCount = ($allItems | Where-Object {$_.PSIsContainer}).Count
        $subFileCount = $subFiles.Count
        $subFileBytes = ($subFiles | Measure-Object Length -Sum).Sum

        # 格式化当前子文件夹的输出行,和原有格式保持完全一致
        $subSizeGB = "{0:N2}" -f ($subFileBytes / 1GB)
        Write-Output "$subSizeGB $Tab $Tab $subFileCount $Tab $Tab $subDirCount $Tab $Tab $($subDir.Name)"

        # 累加到总统计值
        $TotalBytes += $subFileBytes
        $TotalFiles += $subFileCount
        $TotalFolders += $subDirCount
    }

    # 计算最终汇总值
    $TotalFolders += $rootDirectFolderCount
    $TotalSizeGB = "{0:N2}" -f ($TotalBytes / 1GB)
    $subTotalSizeGB = "{0:N2}" -f (($TotalBytes - $rootDirectFileBytes)/1GB)

    Write-Output " "
    Write-Output " "
    Write-Output "Total in '$startDirectory':"
    Write-Output " "
    Write-Output "Size: $TotalSizeGB GB ($subTotalSizeGB GB in sub-folders)"
    Write-Output "Files: $TotalFiles ($($TotalFiles - $rootDirectFileCount) in sub-folders)"
    Write-Output "Folders: $TotalFolders ($($TotalFolders - $rootDirectFolderCount) in sub-folders)"
} | Tee-Object -FilePath $logPath

# 统计完成自动打开日志文件
Invoke-Item $logPath

运行时的表现

  • 脚本启动后,开头的提示文字会以带颜色的样式显示在控制台,不会写入日志文件
  • 表头信息输出后,每处理完一个子文件夹,对应的行立刻刷出在控制台,同时实时写入日志,随时能看到处理进度
  • 所有文件夹统计完成后,自动汇总最终的总大小、总文件数、总文件夹数,最后自动打开生成的Output.txt文件

内容的提问来源于stack exchange,提问作者Simon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.12 01:36:04