如何根据文件名的一部分选择文件夹中的文件并在Powershell中压缩它们?

时间:2015-07-08 11:41:35

标签: powershell zip

我是Powershell的新手(使用Powershell 2.0顺便说一句),我正在尝试创建一个可以执行多项操作的脚本(这是我的第三个脚本左右)。我有大部分的东西,但剩下的最后一件事是根据文件名的第一部分(前三个字符)将不同类型的文件(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本地并使其工作,但后来只有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个字符为我提供了lates created文件夹中的分组文件列表。它还显示每个组中的文件。 如下所示:

计数名称组
----- ---- -----
    3 003 {C:\ Test \ 20150708 063255_B \ 003.metafile.xml,C:\ Test \ 20150708 063255_B \ 003.tfw,C:\ Test \ 20150708 063255_B \ 003.tif}
    6 004 {C:\ Test \ 20150708 063255_B \ 004.metafile.xml,C:\ Test \ 20150708 063255_B \ 004.tfw,C:\ Test \ 20150708 063255_B \ 004.tif,C:\ Test ...     6 009 {C:\ Test \ 20150708 063255_B \ 009.metafile.xml,C:\ Test \ 20150708 063255_B \ 009.tfw,C:\ Test \ 20150708 063255_B \ 009.tif,C:\ Test ...

现在我的下一步是取这些组并压缩它们。理想情况下,在不同的目标目录中创建这些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版权所有(c)1999-2010 Igor Pavlov 2010-11-18错误:   c:\ Test \ Dest_test460.zip不支持存档系统错误:   功能不正确。

,或者

  

警告:找不到1个文件7-Zip(A)9.20版权所有(c)1999-2010   Igor Pavlov 2010-11-18扫描\ 460:警告:系统不能   找到指定的文件。

,或者它开始将我的userprofile上的所有文件压缩成zip文件。取决于我对$ group-value所做的更改。我相信我的脚本中有一个更基本的错误导致这个,这就是我要求帮助的地方。可能是我通过首先分组我想要的文件然后尝试压缩它们来接近这个错误的方法?

任何人都可以看到我的错误或给我一些暗示我必须做的事情?

谢谢你的时间!

3 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

使用我的上一个答案函数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)中对其进行更改,并在需要时将其设置为不同。

祝你好运

答案 2 :(得分:0)

无法使建议的解决方案起作用,在配置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