【问题标题】:Using a text file as input to a Powershell script使用文本文件作为 Powershell 脚本的输入
【发布时间】:2015-07-08 04:05:14
【问题描述】:

我的团队正在迁移到一个新网络,我们无法直接从网络 A 中的计算机复制到网络 B 中的新机器。在网络 A 中的这台机器上使用多年后,我的项目文件散布在各处磁盘。我需要构建一个脚本来将文件夹和文件复制到备份磁盘。那里没问题,但是网络技术人员要求在复制之前知道总字节数

在 CMD 中,我使用来自 C:\dir /AD /S /B > C:\Users\r6540\Desktop\UserFiles.txt 来生成一个巨大的目录列表,其中包括很多我手动编辑的垃圾。

例如

C:\Dev\SSIS
C:\Dev\SSIS\DatabaseCleanup
C:\Dev\SSIS\DatabaseMaintTests
C:\Dev\SSIS\EclipseKeys
C:\Dev\SSIS\TemplateProject

我从未使用过 PowerShell,但看起来这项任务确实是在它的能力范围内。我发现了这个:

$startFolder = "C:\Scripts"

$colItems = (Get-ChildItem $startFolder | Measure-Object -property length -sum)
"$startFolder -- " + "{0:N2}" -f ($colItems.sum / 1MB) + " MB"

$colItems = (Get-ChildItem $startFolder -recurse | Where-Object {$_.PSIsContainer -eq $True} | Sort-Object)
foreach ($i in $colItems)
    {
        $subFolderItems = (Get-ChildItem $i.FullName | Measure-Object -property length -sum)
        $i.FullName + " -- " + "{0:N2}" -f ($subFolderItems.sum / 1MB) + " MB"
    }

Microsoft technet 和这个,同一页面:

$objFSO = New-Object -com  Scripting.FileSystemObject
"{0:N2}" -f (($objFSO.GetFolder("C:\Scripts").Size) / 1MB) + " MB"

我要查找的输出是目录名称、选项卡和文件夹大小(但没有上面显示的“MB”)和 CRLF 作为写入文本文件的 EOL。

例如

C:\Dev\SSIS 70.23
C:\Dev\SSIS\DatabaseCleanup 17.80
C:\Dev\SSIS\DatabaseMaintTests  22.91
C:\Dev\SSIS\EclipseKeys 1.22
C:\Dev\SSIS\TemplateProject 13.29

任何人都知道 PowerShell 足以通过 UserFiles.txt 并获得结果文本文件输出?

形式并不像功能那么重要——所以如果你能想出另一种方法,我会很高兴看到它。

谢谢。

【问题讨论】:

  • 那么您的示例输出是否满足您的需求,您需要一种方法来仅使用文本文件作为输入并使用单独的文件作为输出?
  • 没错。输出文件基本上只是在 EOL 之前插入选项卡和文件夹大小的输入文件。

标签: shell powershell batch-file cmd


【解决方案1】:

这在 PowerShell 中非常简单:

$objFSO = New-Object -com  Scripting.FileSystemObject
Get-Content c:\input.txt |
    Foreach { "{0}`t{1:N2}" -f $_, (($objFSO.GetFolder($_).Size) / 1MB) } |
    Out-File c:\output.txt -enc ascii

这是假设您找到的 FileSystemObject 脚本有效。 :-)

【讨论】:

  • 这很好用,除了分隔符是空格而不是制表符。显然,当我粘贴输入文件文本时,选项卡被洗掉了。输出文件成为数据库上传过程的输入文件,空格导致错误。知道我们可以在其中填充制表符的方法吗?
  • 您可以在双引号字符串中使用<backtick>t 填充制表符字符。查看更新的答案。
  • 完美!这会生成所需的确切文件格式。谢谢,凯文!
【解决方案2】:

简单的方法是更有效地使用管道

$inputFile = "C:\Users\r6540\Desktop\UserFiles.txt"
$outputFile = "C:\temp\output.txt"

Get-Content $inputFile | ForEach-Object{
    $sum = Get-ChildItem $_ -recurse -Force | Measure-Object -property length -sum | Select-Object -ExpandProperty Sum
    "{1}`t{0:N2}" -f ($sum / 1MB), $_
} | Set-Content $outputFile

因此,我们使用您发布的逻辑获取文件的每一行并以 MB 为单位收集大小。将输出发送到文件。但是我们可以稍微改进一下。

$inputFile = "C:\Users\r6540\Desktop\UserFiles.txt"
$outputFile = "C:\temp\output.txt"

$results = Get-Content $inputFile | ForEach-Object{
    $props = @{
        Folder = $_
        Sum = "{0:N2}" -f ((Get-ChildItem $_ -Recurse -Force | Measure-Object -property length -sum | Select-Object -ExpandProperty Sum) / 1MB)
    }

    New-Object -TypeName PSCustomObject -Property $props
}

$results | Export-CSV $outputFile -NoTypeInformation
"Total,{0}" -f ($results | Measure-Object Sum -sum | Select-Object -ExpandProperty Sum) | Add-Content $outputFile

这里唯一的区别是我们制作了漂亮的 CSV 输出,以及从一天结束时将总数附加到底部,这可能也很高兴知道(如果我是来自多个用户的多个副本的接收者我会为我节省几秒钟的精力。)您也可以为此在循环中保留一个计数器,但这让您有机会看到 PowerShell 的工作情况。

【讨论】:

  • 要使用 Get-ChildItem 获取真实大小,请使用 -Force 使其列出隐藏文件。
  • @KeithHill 这是真的。
  • 第一个脚本接近了,但分隔符是“--”,我需要一个制表符,因为这里的输出文件成为另一个进程的输入文件。也感谢总/CSV 版本 - 非常说明性。
  • @JimtheFrayed 替换为制表符
猜你喜欢
  • 2021-03-23
  • 2013-07-10
  • 1970-01-01
  • 1970-01-01
  • 2014-02-04
  • 1970-01-01
  • 1970-01-01
  • 2017-10-02
  • 1970-01-01
相关资源
最近更新 更多