PowerShell 脚本未压缩正确的文件

问题描述 投票:0回答:2
 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 程序文件夹的内容。什么可能导致这种情况?预先感谢

powershell zip target 7zip get-childitem
2个回答
10
投票

使用其 Zip 属性

(PSv3+ 语法)将文件作为 
完整路径
传递到 
.FullName
函数:

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

问题是,Windows PowerShell 中,

[System.IO.FileInfo]
 
situationally
[1] 返回的 Get-ChildItem 实例仅字符串化为它们的 文件名
,这就是您的情况发生的情况,因此您的
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] 

When

Get-ChildItem 输出仅字符串化到文件 names

注:

    如果
  • Get-ChildItem

    输出要传递到其他文件处理cmdlet

    ,例如Rename-Item
    可以通过管道
    向它们提供输入来绕过问题,其中通过完整路径隐式绑定到目标 cmdlet 的 -LiteralPath 参数 - 有关更多信息,请参阅此答案
    
    

    相关的
  • Get-Item

    cmdlet 输出总是

    字符串化为完整路径,
    幸运的是。

  • PowerShell(核心)
  • v6.1+ 中,

    Get-ChildItem总是字符串化为完整路径

    ,幸运的是。
    因此,以下内容

    仅适用于
  • Windows PowerShell

中的 Get-ChildItem

问题是双重的:

甚至 PowerShell 的内置 cmdlet 也不会将文件/目录

arguments
    (参数值 - 与通过
  • pipeline

    输入相对)绑定为 objects,而是作为 stringsGitHub 中正在讨论更改此行为)问题#6057)。 因此,为了实现稳健的参数传递,您需要确保

    Get-ChildItem
  • 输出一致地字符串化为
  • 完整路径

    ,而

    Get-ChildItem
    确实保证——并且很容易忘记当
    仅名称
    字符串化时发生甚至需要引起注意。

    始终传递
  • .FullName
属性值是最简单的解决方法

,或者,为了与 任何

 PowerShell 提供程序(而不仅仅是文件系统)进行可靠操作,
.PSPath
[System.IO.FileInfo]
命令输出的

[System.IO.DirectoryInfo]

Get-ChildItem
实例仅字符串化到其文件
names
当且仅当
:
如果

一个或多个
    文字目录路径
  • 传递给-LiteralPath-Path(可能作为第一个位置参数)

    根本没有路径被传递(目标当前位置) ;也就是说,如果枚举目录的contents
    
    

  • 使用-Include/-Exclude参数

    (是否使用
    -Filter
    没有
    区别)。
    相比之下,无论是否存在以下内容,都没有区别:

  • -Filter(可选作为 2nd

    位置参数,但请注意,指定通配符表达式,例如
      *.txt
    • 作为
      1st
      (也可能是唯一)位置参数绑定到 -Path 参数)
      -Recurse(由
      本身
      ,但请注意,它经常与
    • -Include
    • /
      -Exclude
      结合使用)
      
      
      示例命令:
  • # 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

如果您(暂时)禁用

|Out-Null
,您将看到传递的错误消息。
$Files 包含对象而不仅仅是文件名数组。

1
投票
默认情况下,powershell 尝试使用不包含路径的

Name

 属性对其进行字符串化 - 因此 7zip 无法找到文件,因为您还更改了 7zip 文件夹的路径(并且 -recurse 收集 $files)

所以改变线路

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


并追加

| Select-Object -ExpandProperty FullName

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

Function Zip{ Param ( [string]$zipFile, [string[]]$toBeZipped ) & "C:\Program Files\7-Zip\7z.exe" A -tzip $zipFile $toBeZipped | Out-Null } $Days = "60" $LastWrite = (Get-Date).Date.AddDays(-$Days) $TargetFolder = "$($ENV:USERPROFILE)\Downloads\*" $Files = Get-Childitem $TargetFolder -Recurse | Where {$_.LastWriteTime -le $LastWrite} | Select-Object -ExpandProperty FullName $Files Zip "$($ENV:USERPROFILE)\Desktop\TEST.zip" $Files

© www.soinside.com 2019 - 2024. All rights reserved.