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 程序文件夹的内容。什么可能导致这种情况?预先感谢
使用其 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]
Get-ChildItem
输出仅字符串化到文件 names
:注:
Get-ChildItem
输出要传递到其他文件处理cmdlet
,例如Rename-Item
,可以通过管道向它们提供输入来绕过问题,其中通过完整路径隐式绑定到目标 cmdlet 的
-LiteralPath
参数 - 有关更多信息,请参阅此答案。
相关的 Get-Item
cmdlet 输出总是
字符串化为完整路径,幸运的是。 在
Get-ChildItem
也总是字符串化为完整路径
,幸运的是。因此,以下内容 仅适用于
中的 Get-ChildItem
:问题是双重的:
甚至 PowerShell 的内置 cmdlet 也不会将文件/目录
arguments输入相对)绑定为 objects,而是作为 strings(GitHub 中正在讨论更改此行为)问题#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 包含对象而不仅仅是文件名数组。
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