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
函数,使用它们的.FullName
属性(PSv3+语法):
Zip C:\Users\Admin\Desktop\TEST.zip $Files.FullName
问题是,在Windows PowerShell中,由
[System.IO.FileInfo]
situationally[1]返回的Get-ChildItem
实例仅字符串化为它们的文件名,这就是你的情况,因此您的 Zip
函数然后将 $toBeZipped
值解释为 relative 到当前位置,即 C:\Program Files\7-Zip
在那个点。
就是说,最好不要在你的函数中完全使用
Set-Location
,这样如果你do想要传递实际的relative路径,它们会被正确地解释为相对于current位置:
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
参数 - 有关更多信息,请参阅this answer。
相关的Get-Item
在 PowerShell (Core) v6.1+ 中,Get-ChildItem
always stringifies to the full path, 幸运的是。
以下仅适用于Get-ChildItem
在Windows PowerShell中: 问题是双重的:
arguments(参数值 - 与通过pipeline输入相反)不是作为objects,而是作为strings(更改此行为正在讨论GitHub问题 #6057).
Get-ChildItem
输出始终字符串化为完整路径,而
Get-ChildItem
确实not 保证 - 而且当 name-only 字符串化时很容易忘记发生或什至你需要注意它。
始终传递 .FullName
属性值是最简单的解决方法或者,为了与 any PowerShell 提供程序(而不仅仅是文件系统)进行可靠操作,
.PSPath
.
[System.IO.FileInfo]
和
[System.IO.DirectoryInfo]
实例输出由
Get-ChildItem
命令字符串化到他们的文件names only, if and only if:
一个或多个文字目录路径传递给-LiteralPath
或
-Path
(可能作为第一个位置参数)或根本没有传递路径(定位当前位置) ;也就是说,如果枚举目录的contents。
和不also使用-Include
/
-Exclude
参数(是否使用
-Filter
使得no不同)。
no不同:
-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 文件夹的路径(并且递归收集 $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