如何根据部分文件名 select 文件夹中的文件并将它们压缩到 Powershell 中?
How do I select files in a folder based on part of filename and zip them in Powershell?
我是 Powershell 的新手(顺便说一句,使用 Powershell 2.0),我正在尝试制作一个可以做几件事的脚本(这是我的第 3 个左右的脚本)。我已经准备好了大部分东西,但剩下的最后一件事是根据文件名的第一部分(前三个字符)将不同类型的文件(xml、tfw 和 tif)分组到一个文件夹中,然后压缩这些文件将文件分成几个 zip 文件,名称与前 3 个字符相同,位于相同位置或新位置。
文件夹内容示例:
001.tif
001.tfw
001.metadata.xml
002.tif
002.tfw
002.metadata.xml
003.tif
003.tfw
003.metadata.xml
003_svel.tif
003_svel.tfw
003_svel.metadata.xml
想要的结果:
001.zip containing 001.tif, 001.tfw, 001.metadata.xml
002.zip containing 002.tif, 002.tfw, 002.metadata.xml
003.zip containing 003.tif, 003.tfw, 003.metadata.xml, 003_svel.tif,
003_svel.tfw and 003_svel.metadata.xml
我已经安装了 7-zip 来进行压缩,并且我正在使用命令行版本。我在一些测试文件上使用了 7-zip local 并让它工作,但它只是 tif 文件。我有一个源文件夹,我在其中搜索最新创建的文件夹,然后处理其中的文件。
这是我目前所拥有的(Powershell 2.0):
$dir_source = "c:\Test"
$new_folder = Get-ChildItem $dir_source -Recurse |
Where { $_.PSIsContainer} |
Sort-Object LastWriteTime -Descending |
Select-Object -ExpandProperty Fullname <-First 1
Get-ChildItem $new_folder -recurse -Exclude metafile.xml |
Group-Object {$_.Name.Substring(0,3)}
这会根据文件名中的前 3 个字符为我提供最近创建的文件夹中的分组文件列表。它还显示每个组中的文件。
如下所示:
计数名称组
----- ---- -----
3 003 {C:\Test150708 063255_B[=49=]3.metafile.xml, C:\Test150708 063255_B[=49=]3.tfw, C:\Test150708 063255_B[=49=]3. tif}
6 004 {C:\Test150708 063255_B[=55=]4.metafile.xml, C:\Test150708 063255_B[=55=]4.tfw, C:\Test150708 063255_B[=55=]4. tif,C:\测试...
6 009 {C:\Test150708 063255_B[=61=]9.metafile.xml, C:\Test150708 063255_B[=61=]9.tfw, C:\Test150708 063255_B[=61=]9. tif,C:\测试...
现在我的下一步是获取这些组并将它们压缩。理想情况下,在不同的目标目录中创建这些 zip 文件(我相信我可以在下面的脚本中设置 $directory- 变量时更改它。)
foreach ($group in $dataset) {
$name = $file.name
$directory = $file.DirectoryName
$zipFile = $file.Name + ".zip"
sz a -t7z "$directory$zipfile" "$directory$name"
这最后一段代码引起了一些麻烦。我要么收到消息:
7-Zip (A) 9.20 Copyright (c) 1999-2010 Igor Pavlov 2010-11-18 Error:
c:\Test\Dest_test460.zip is not supported archive System error:
Incorrect function.
,或
WARNING: Cannot find 1 file 7-Zip (A) 9.20 Copyright (c) 1999-2010
Igor Pavlov 2010-11-18 Scanning 0: WARNING: The system cannot
find the file specified.
,或者它开始将我的用户配置文件中的所有文件压缩到一个 zip 文件中。根据我对 $group-value 所做的更改。我相信我的脚本中有一个或多个基本错误导致了这一点,这就是我寻求帮助的地方。可能是我通过首先对我想要的文件进行分组然后尝试压缩它们来以错误的方式处理这个问题?
任何人都可以看到我的错误或给我一些提示我必须做什么?
感谢您的宝贵时间!
Lee Holmes New-ZipFile 完成这项工作,他有两个版本,其中一个使用 ICSharpCode.SharpZipLib.dll 压缩,另一个不需要它,我将第二个包装成一个函数:
Function New-ZipFile {
param(
## The name of the zip archive to create
$Path = $(throw "Specify a zip file name"),
## Switch to delete the zip archive if it already exists.
[Switch] $Force
)
Set-StrictMode -Version 3
## Create the Zip File
$zipName = $executionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
## Check if the file exists already. If it does, check
## for -Force - generate an error if not specified.
if(Test-Path $zipName)
{
if($Force)
{
Remove-Item $zipName -Force
}
else
{
throw "Item with specified name $zipName already exists."
}
}
## Add the DLL that helps with file compression
Add-Type -Assembly System.IO.Compression.FileSystem
try
{
## Open the Zip archive
$archive = [System.IO.Compression.ZipFile]::Open($zipName, "Create")
## Go through each file in the input, adding it to the Zip file
## specified
foreach($file in $input)
{
## Skip the current file if it is the zip file itself
if($file.FullName -eq $zipName)
{
continue
}
## Skip directories
if($file.PSIsContainer)
{
continue
}
$item = $file | Get-Item
$null = [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile(
$archive, $item.FullName, $item.Name)
}
}
finally
{
## Close the file
$archive.Dispose()
$archive = $null
}
}
使用示例:
dir c:\folder -Recurse | New-ZipFile -Path c:\temp\folder.zip
源文件(使用ICSharpCode的):http://poshcode.org/2202
使用我以前的答案函数 New-ZipFile 并与这个一起使用:
$FolderName = "C:\temp"
$Files = dir $FolderName
$prfx = @()
foreach ($file in $files)
{
$prfx += $file.Name.Substring(0,3)
}
$prfx = $prfx | Group
foreach ($Prf in $prfx)
{
$prf = $prf.name.ToString()
dir $Files | ? {$_.Name -match "^$prf"} | New-ZipFile -Path "$foldername$prf.zip"
}
根据您的示例,它将输出 3 个您想要的 zip 文件,
它将始终使用文件的前 3 个字母,您可以在此行中更改此 $prfx += $file.Name.Substring(0,3)
并根据需要设置不同。
祝你好运
无法使建议的解决方案起作用,配置 ICSharpCode 时遇到问题。我也想使用 7zip,因为它仍在某种更新机制下。
最后根据文件名将我的文件复制到临时文件夹,然后压缩每个文件夹。之后删除带有文件的临时文件夹。丑陋的代码,但它完成了工作。
# Create folder based on filename and copy files into respective folder
Get-ChildItem $new_folder -Filter *.* | Where-Object {!$_.PSIsContainer} | Foreach-Object{
$dest = Join-Path $_.DirectoryName $_.Name.SubString(0,3)
if(!(Test-Path -Path $dest -PathType Container))
{
$null = md $dest
}
$_ | Copy-Item -Destination $dest -Force
}
# Create zip-file of each folder
dir $new_folder | Where-Object { $_.PSIsContainer } | ForEach-Object { sz a -t7z -mx9 "$dir_dest$_.zip" $_.FullName }
# Delete temp-folders
dir $new_folder | Where-Object { $_.PSIsContainer } | Remove-Item -Recurse
我是 Powershell 的新手(顺便说一句,使用 Powershell 2.0),我正在尝试制作一个可以做几件事的脚本(这是我的第 3 个左右的脚本)。我已经准备好了大部分东西,但剩下的最后一件事是根据文件名的第一部分(前三个字符)将不同类型的文件(xml、tfw 和 tif)分组到一个文件夹中,然后压缩这些文件将文件分成几个 zip 文件,名称与前 3 个字符相同,位于相同位置或新位置。
文件夹内容示例:
001.tif
001.tfw
001.metadata.xml
002.tif
002.tfw
002.metadata.xml
003.tif
003.tfw
003.metadata.xml
003_svel.tif
003_svel.tfw
003_svel.metadata.xml
想要的结果:
001.zip containing 001.tif, 001.tfw, 001.metadata.xml
002.zip containing 002.tif, 002.tfw, 002.metadata.xml
003.zip containing 003.tif, 003.tfw, 003.metadata.xml, 003_svel.tif,
003_svel.tfw and 003_svel.metadata.xml
我已经安装了 7-zip 来进行压缩,并且我正在使用命令行版本。我在一些测试文件上使用了 7-zip local 并让它工作,但它只是 tif 文件。我有一个源文件夹,我在其中搜索最新创建的文件夹,然后处理其中的文件。 这是我目前所拥有的(Powershell 2.0):
$dir_source = "c:\Test"
$new_folder = Get-ChildItem $dir_source -Recurse |
Where { $_.PSIsContainer} |
Sort-Object LastWriteTime -Descending |
Select-Object -ExpandProperty Fullname <-First 1
Get-ChildItem $new_folder -recurse -Exclude metafile.xml |
Group-Object {$_.Name.Substring(0,3)}
这会根据文件名中的前 3 个字符为我提供最近创建的文件夹中的分组文件列表。它还显示每个组中的文件。 如下所示:
计数名称组
----- ---- -----
3 003 {C:\Test150708 063255_B[=49=]3.metafile.xml, C:\Test150708 063255_B[=49=]3.tfw, C:\Test150708 063255_B[=49=]3. tif}
6 004 {C:\Test150708 063255_B[=55=]4.metafile.xml, C:\Test150708 063255_B[=55=]4.tfw, C:\Test150708 063255_B[=55=]4. tif,C:\测试...
6 009 {C:\Test150708 063255_B[=61=]9.metafile.xml, C:\Test150708 063255_B[=61=]9.tfw, C:\Test150708 063255_B[=61=]9. tif,C:\测试...
现在我的下一步是获取这些组并将它们压缩。理想情况下,在不同的目标目录中创建这些 zip 文件(我相信我可以在下面的脚本中设置 $directory- 变量时更改它。)
foreach ($group in $dataset) {
$name = $file.name
$directory = $file.DirectoryName
$zipFile = $file.Name + ".zip"
sz a -t7z "$directory$zipfile" "$directory$name"
这最后一段代码引起了一些麻烦。我要么收到消息:
7-Zip (A) 9.20 Copyright (c) 1999-2010 Igor Pavlov 2010-11-18 Error: c:\Test\Dest_test460.zip is not supported archive System error: Incorrect function.
,或
WARNING: Cannot find 1 file 7-Zip (A) 9.20 Copyright (c) 1999-2010 Igor Pavlov 2010-11-18 Scanning 0: WARNING: The system cannot find the file specified.
,或者它开始将我的用户配置文件中的所有文件压缩到一个 zip 文件中。根据我对 $group-value 所做的更改。我相信我的脚本中有一个或多个基本错误导致了这一点,这就是我寻求帮助的地方。可能是我通过首先对我想要的文件进行分组然后尝试压缩它们来以错误的方式处理这个问题?
任何人都可以看到我的错误或给我一些提示我必须做什么?
感谢您的宝贵时间!
Lee Holmes New-ZipFile 完成这项工作,他有两个版本,其中一个使用 ICSharpCode.SharpZipLib.dll 压缩,另一个不需要它,我将第二个包装成一个函数:
Function New-ZipFile {
param(
## The name of the zip archive to create
$Path = $(throw "Specify a zip file name"),
## Switch to delete the zip archive if it already exists.
[Switch] $Force
)
Set-StrictMode -Version 3
## Create the Zip File
$zipName = $executionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
## Check if the file exists already. If it does, check
## for -Force - generate an error if not specified.
if(Test-Path $zipName)
{
if($Force)
{
Remove-Item $zipName -Force
}
else
{
throw "Item with specified name $zipName already exists."
}
}
## Add the DLL that helps with file compression
Add-Type -Assembly System.IO.Compression.FileSystem
try
{
## Open the Zip archive
$archive = [System.IO.Compression.ZipFile]::Open($zipName, "Create")
## Go through each file in the input, adding it to the Zip file
## specified
foreach($file in $input)
{
## Skip the current file if it is the zip file itself
if($file.FullName -eq $zipName)
{
continue
}
## Skip directories
if($file.PSIsContainer)
{
continue
}
$item = $file | Get-Item
$null = [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile(
$archive, $item.FullName, $item.Name)
}
}
finally
{
## Close the file
$archive.Dispose()
$archive = $null
}
}
使用示例:
dir c:\folder -Recurse | New-ZipFile -Path c:\temp\folder.zip
源文件(使用ICSharpCode的):http://poshcode.org/2202
使用我以前的答案函数 New-ZipFile 并与这个一起使用:
$FolderName = "C:\temp"
$Files = dir $FolderName
$prfx = @()
foreach ($file in $files)
{
$prfx += $file.Name.Substring(0,3)
}
$prfx = $prfx | Group
foreach ($Prf in $prfx)
{
$prf = $prf.name.ToString()
dir $Files | ? {$_.Name -match "^$prf"} | New-ZipFile -Path "$foldername$prf.zip"
}
根据您的示例,它将输出 3 个您想要的 zip 文件,
它将始终使用文件的前 3 个字母,您可以在此行中更改此 $prfx += $file.Name.Substring(0,3)
并根据需要设置不同。
祝你好运
无法使建议的解决方案起作用,配置 ICSharpCode 时遇到问题。我也想使用 7zip,因为它仍在某种更新机制下。
最后根据文件名将我的文件复制到临时文件夹,然后压缩每个文件夹。之后删除带有文件的临时文件夹。丑陋的代码,但它完成了工作。
# Create folder based on filename and copy files into respective folder
Get-ChildItem $new_folder -Filter *.* | Where-Object {!$_.PSIsContainer} | Foreach-Object{
$dest = Join-Path $_.DirectoryName $_.Name.SubString(0,3)
if(!(Test-Path -Path $dest -PathType Container))
{
$null = md $dest
}
$_ | Copy-Item -Destination $dest -Force
}
# Create zip-file of each folder
dir $new_folder | Where-Object { $_.PSIsContainer } | ForEach-Object { sz a -t7z -mx9 "$dir_dest$_.zip" $_.FullName }
# Delete temp-folders
dir $new_folder | Where-Object { $_.PSIsContainer } | Remove-Item -Recurse