PowerShell脚本未压缩正确的文件

时间:2018-11-20 18:40:07

标签: powershell scripting zip target 7zip

 Function Zip
{
    Param
    (
        [string]$zipFile
        ,
        [string[]]$toBeZipped
    )
    $CurDir = Get-Location
    Set-Location "C:\Program Files\7-Zip"
    .\7z.exe A -tzip $zipFile $toBeZipped | Out-Null
    Set-Location $CurDir
}
$Now = Get-Date
$Days = "60"
$TargetFolder = "C:\users\Admin\Downloads\*.*"
$LastWrite = $Now.AddDays(-$Days)
$Files = Get-Childitem $TargetFolder -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}
$Files
Zip C:\Users\Admin\Desktop\TEST.zip $Files

我正在测试我在网上找到的脚本。我的问题是,不是压缩目标文件夹中的文件,而是复制并压缩7-zip程序文件文件夹的内容。是什么原因造成的?预先感谢

2 个答案:

答案 0 :(得分:4)

使用文件的Zip属性(PSv3 +语法)将文件作为完整路径 传递到.FullName函数:

Zip C:\Users\Admin\Desktop\TEST.zip $Files.FullName

问题是由[System.IO.FileInfo]返回的{strong> Get-ChildItem个实例按情况 [1] 字符串化为其文件名仅 ,这就是您遇到的情况,因此您的Zip函数会将$toBeZipped的值解释为相对于当前位置的 此时是C:\Program Files\7-Zip

也就是说,最好不要在函数中完全使用Set-Location ,这样,如果您要做要通过实际的相对路径,它们被正确解释为相对于当前位置:

Function Zip {
    Param
    (
        [Parameter(Mandatory)] # make sure a value is passed          
        [string]$zipFile
        ,
        [Parameter(Mandatory)] # make sure a value is passed
        [string[]]$toBeZipped
    )
    # Don't change the location, use & to invoke 7z by its full path.
    $null = & "C:\Program Files\7-Zip\7z.exe" A -tzip $zipFile $toBeZipped
    # You may want to add error handling here.
}

[1] 何时 Get-ChildItem输出仅字符串化到文件名称

注意:

  • Get-Item输出始终幸运地将字符串化为完整路径。
  • 在PowerShell Core 中,Get-ChildItem也总是 字符串化为完整路径,这值得称赞,但这是{{3 }}。

因此,以下内容仅适用于 Windows PowerShell 中的Get-ChildItem

问题是双重的:

  • 即使PowerShell的内置cmdlet绑定文件/目录参数(参数值-与通过管道输入的参数相反)也不是 objects < / em>,但作为 strings (在unclear whether the change was intentional中讨论更改此行为)。

  • 因此,要进行可靠的参数传递,您需要确保Get-ChildItem输出始终字符串化为完整路径Get-ChildItem不会这样做保证-很容易忘记何时发生仅名称字符串化,甚至根本不需要注意它。

始终传递.FullName属性值是最简单的解决方法,或者,对于 any PowerShell提供程序的可靠操作,不仅仅是文件系统, .PSPath

[System.IO.FileInfo]命令输出的

[System.IO.DirectoryInfo]Get-ChildItem实例仅字符串化到其文件 names 仅当且仅当 em>

  • 如果将一个或多个文字目录路径 传递给-LiteralPath-Path(可能是第一个位置参数)< em>或 完全没有路径 (定位到当前位置);也就是说,如果枚举目录的内容

  • 不使用-Include / -Exclude参数(无论{{1 }}的使用使没有有所不同)。

  • 相比之下,是否还存在以下内容使没有有所不同:

    • -Filter(可选地作为 2nd 位置参数,但请注意,将通配符表达式(例如-Filter指定为 1st )(并且可能仅)位置参数绑定到*.txt参数)
    • -Path(通过本身,但请注意,它通常与-Recurse / -Include结合使用)

示例命令:

-Exclude

答案 1 :(得分:1)

如果(暂时)禁用# NAME-ONLY stringification: Get-ChildItem | % ToString # no target path Get-ChildItem . | % ToString # path is literal dir. Get-ChildItem . *.txt | % ToString # path is literal dir., combined with -Filter # FULL PATH stringification: Get-ChildItem foo* | % ToString # non-literal path (wildcard) Get-ChildItem -Recurse -Include *.txt | % ToString # use of -Include Get-ChildItem file.txt | % ToString # *file* path ,您会看到味精传递的错误。
$ Files包含对象而不仅仅是文件名数组。

默认情况下,powershell尝试使用不包含路径的|Out-Null属性对此进行字符串化-因此7zip找不到文件,因为您还更改了7zip文件夹的路径(并且-recurse收集$文件)

因此更改行

Name

并追加

$Files = Get-Childitem $TargetFolder -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}

您的来源的格式稍稍重新格式化的版本:

| Select-Object -ExpandProperty FullName