转换现有函数以处理多个文件以解压缩

时间:2015-05-04 22:11:05

标签: file powershell compression

我有一个现有的工作代码来解压缩gz格式的文件:

\author{...}

是否可以使用此代码解压缩文件夹中的所有.gz文件?参数如何传递给脚本。我假设现在不是文件名,而是应该查找输入目录和目标文件夹。

2 个答案:

答案 0 :(得分:1)

目前看来它只是看起来像是在问你如何将你的功能融入循环中。 Etan Reisner试图帮助你做到这一点。在他的评论的基础上,你可以做一些事情。此信息位于about_functions

$path = "c:\temp\somepath"
Get-ChildItem -Path $path -Filter "*.gz" | ForEach-Object{
    DeGZip-File -inifile $_.FullName
    # Or the following would also work
    # DeGZip-File $_.FullName
}
根据您的功能设置方式,

-outfile可视为可选项。如果你需要通过函数调用声明它,那么你只需要在循环中执行此操作

DeGZip-File -inifile $_.FullName -outfile "otherFileName"

DeGZip-File $_.FullName "SomehtingElse"

<强>除了

考虑查看Advanced Functions,您可以让您的函数接受管道输入。

答案 1 :(得分:1)

正如其他人所提到的,您可以简单地将您的函数合并到ForEach-Object循环中。或者,如果您创建两个参数集,并且在一个参数集中保留它,并且另一个参数集接受参数上的管道值,并使该参数成为[FileInfo]对象,则可以轻松使用Get-ChildObject管道到你的功能,甚至不必使用循环。至于想要在另一个文件夹中输出,请在函数中添加一个参数,并使用一点内部逻辑来适应...

Function DeGZip-File{
[cmdletbinding(DefaultParameterSetName='Piped')]
    Param(
        [Parameter(ParameterSetName='Direct')][String]$infile,
        [Parameter(ParameterSetName='Direct')][String]$outfile = ($infile -replace '\.gz$',''),
        [Parameter(ParameterSetName='Piped',ValueFromPipeline=$true)][System.IO.FileInfo[]]$PipedFile,
        [Parameter(ParameterSetName='Piped')]$Redirect=$null,
        [Switch]$PassThru
    )

Process{
    If($PsCmdlet.ParameterSetName -eq 'Piped'){
        $infile = $PipedFile.FullName
        $outfile = If([string]::IsNullOrEmpty($Redirect)){$infile -replace '\.gz$',''}else{Join-Path $Redirect -ChildPath ($PipedFile.BaseName)}
    }

    $inputfile = New-Object System.IO.FileStream $inFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read)
    $output = New-Object System.IO.FileStream $outFile, ([IO.FileMode]::Create), ([IO.FileAccess]::Write), ([IO.FileShare]::None)
    $gzipStream = New-Object System.IO.Compression.GzipStream $inputfile, ([IO.Compression.CompressionMode]::Decompress)

    $buffer = New-Object byte[](1024)

    $read = $gzipstream.Read($buffer, 0, 1024)
    Do{
        $output.Write($buffer, 0, $read)
        $read = $gzipstream.Read($buffer, 0, 1024)
    }While($read -gt 0)

    $gzipStream.Close()
    $output.Close()
    $inputfile.Close()

    If($PassThru){[System.IO.FileInfo]$outfile}
    }
}

我还添加了一个-PassThru开关,以防您想要查看它提取的文件。

编辑:我忘了包含一个用法示例,我的不好......

Get-ChildItem "C:\Temp\GZippedFiled\*.gz" | DeGZip-File -Redirect "C:\Temp\Unzipped" -PassThru

这将解压缩&#34; C:\ Temp \ GZippedFiled&#34;中的所有.GZ文件。文件夹,并将在&#34; C:\ Temp \ Unzipped&#34;中写入具有相同(减去.gz)文件名的解压缩文件。夹。它还会显示它提取的文件,显示每个文件的[fileinfo]对象(Mode,LastWriteTime,Length和Name)。或者你可以更简单地做到这一点,只需管道到没有任何参数的函数,它会在适当的位置提取它们而不向控制台输出任何内容。

它也接受旧的用法,ala:

DeGZip-File -infile "C:\Path\To\File.gz" -outfile "C:\Path\To\NewFile.ext"

Edit2:好的,只是为了确保我在评论中理解了这个问题。我们假设您压缩了2个文件:

C:\Temp\Resume.docx.gz
C:\Temp\Cover Letter.docx.gz

您想要解压缩它们,并将结果文件存储在C:\Temp\Unzipped中(目标文件夹应该已经存在)。您的脚本应该具有顶部的功能,然后您可以根据需要定义路径,然后将Get-ChildItem传递给函数。看起来应该是这样的:

Function DeGZip-File{
    <function code goes here>
}

$FullPath = 'C:\Temp\'
$DestinationPath = 'C:\Temp\Unzipped'

Get-ChildItem -Path $fullpath -Filter "*.gz" | DeGZip-File -Redirect $destinationpath -PassThru

我只是将这个答案中的函数复制到一个新的PowerShell ISE实例,将2 .gz文件放在我的C:\ Temp文件夹中,创建了一个C:\ Temp \ Unzipped文件夹,然后运行上面的代码。它功能完美。提取的文件,它向我展示了它们的详细信息。路径上的尾随反斜杠并不重要,两者都没有,或者两条路径都没有或者没有反斜杠,并且因为join-path消毒而无法产生差异它