PowerShell 脚本未压缩正确的文件
PowerShell script not zipping correct files
Function Zip
{
Param
(
[string]$zipFile
,
[string[]]$toBeZipped
)
$CurDir = Get-Location
Set-Location "C:\Program Files-Zip"
.z.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 中,Get-ChildItem
[=86] 返回的 [System.IO.FileInfo]
个实例=]situationally[1] stringify to their file names only,这就是你的情况,因此您的 Zip
函数随后将 $toBeZipped
值解释为 相对于当前位置 ,即当时的 C:\Program Files-Zip
。
也就是说,最好不要在你的函数中完全使用 Set-Location
,这样万一你做 想要传递实际的 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-Zipz.exe" A -tzip $zipFile $toBeZipped
# You may want to add error handling here.
}
[1] 当 Get-ChildItem
输出字符串化到文件 names only:
注:
如果要将 Get-ChildItem
输出传递给 其他文件处理 cmdlet,说 Rename-Item
, the problem can be bypassed by providing input to them via the pipeline, which implicitly binds to the target cmdlet's -LiteralPath
parameter by full path - see this answer了解更多信息。
相关的Get-Item
cmdlet输出总是字符串化为完整路径,还好。
在 PowerShell (Core) v6.1+ 中,Get-ChildItem
也是 总是 字符串化为完整路径,还好。
因此仅适用于WindowsPowerShell中的Get-ChildItem
:
问题是双重的:
即使是 PowerShell 的内置 cmdlet 也会绑定文件/目录 arguments(参数值 - 与通过 pipeline) 不是 objects,而是 strings(更改此行为正在 GitHub issue #6057 中讨论)。
因此,为了稳健的参数传递,您需要确保您的 Get-ChildItem
输出始终字符串化为 完整路径 ,其中 Get-ChildItem
not 保证 - 很容易忘记什么时候发生 name-only 字符串化,甚至根本不需要注意它。
始终传递 .FullName
属性 值是最简单的解决方法 或者,对于 any[=154= 的可靠操作] PowerShell 提供程序,不仅仅是文件系统,.PSPath
.
[System.IO.FileInfo]
和 [System.IO.DirectoryInfo]
由 Get-ChildItem
命令输出的实例仅字符串化到它们的文件 names,当且仅当:
如果一个或多个文字目录路径传递给-LiteralPath
或-Path
(可能作为第一个位置参数)或根本没有路径被传递(目标当前地点);也就是说,如果枚举了目录的内容。
and 不 also 使用 -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 包含对象,而不仅仅是文件名数组。
默认情况下,powershell 尝试使用不包含路径的 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-Zipz.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
Function Zip
{
Param
(
[string]$zipFile
,
[string[]]$toBeZipped
)
$CurDir = Get-Location
Set-Location "C:\Program Files-Zip"
.z.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 中,Get-ChildItem
[=86] 返回的 [System.IO.FileInfo]
个实例=]situationally[1] stringify to their file names only,这就是你的情况,因此您的 Zip
函数随后将 $toBeZipped
值解释为 相对于当前位置 ,即当时的 C:\Program Files-Zip
。
也就是说,最好不要在你的函数中完全使用 Set-Location
,这样万一你做 想要传递实际的 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-Zipz.exe" A -tzip $zipFile $toBeZipped
# You may want to add error handling here.
}
[1] 当 Get-ChildItem
输出字符串化到文件 names only:
注:
如果要将
Get-ChildItem
输出传递给 其他文件处理 cmdlet,说Rename-Item
, the problem can be bypassed by providing input to them via the pipeline, which implicitly binds to the target cmdlet's-LiteralPath
parameter by full path - see this answer了解更多信息。相关的
Get-Item
cmdlet输出总是字符串化为完整路径,还好。在 PowerShell (Core) v6.1+ 中,
Get-ChildItem
也是 总是 字符串化为完整路径,还好。
因此仅适用于WindowsPowerShell中的Get-ChildItem
:
问题是双重的:
即使是 PowerShell 的内置 cmdlet 也会绑定文件/目录 arguments(参数值 - 与通过 pipeline) 不是 objects,而是 strings(更改此行为正在 GitHub issue #6057 中讨论)。
因此,为了稳健的参数传递,您需要确保您的
Get-ChildItem
输出始终字符串化为 完整路径 ,其中Get-ChildItem
not 保证 - 很容易忘记什么时候发生 name-only 字符串化,甚至根本不需要注意它。
始终传递 .FullName
属性 值是最简单的解决方法 或者,对于 any[=154= 的可靠操作] PowerShell 提供程序,不仅仅是文件系统,.PSPath
.
[System.IO.FileInfo]
和 [System.IO.DirectoryInfo]
由 Get-ChildItem
命令输出的实例仅字符串化到它们的文件 names,当且仅当:
如果一个或多个文字目录路径传递给
-LiteralPath
或-Path
(可能作为第一个位置参数)或根本没有路径被传递(目标当前地点);也就是说,如果枚举了目录的内容。and 不 also 使用
-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 包含对象,而不仅仅是文件名数组。
默认情况下,powershell 尝试使用不包含路径的 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-Zipz.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