简体   繁体   English

如何在Powershell中验证文件是否为zip文件

[英]How to verify if a file is a zip file in Powershell

I receive a collection of files to process monthly from a vendor.我每月从供应商那里收到要处理的文件集合。 The files do not have an extension, but they have a consistent naming convention.这些文件没有扩展名,但它们具有一致的命名约定。 However, the lack of an extension causes some issues when sometimes there is a compressed folder in there with the name of a file I have the code to process.但是,缺少扩展名会导致一些问题,有时其中有一个压缩文件夹,其中包含我要处理的代码的文件名。 So, I'm looking for some way of doing a boolean check on each file to confirm if it is actually a compressed folder.所以,我正在寻找某种方法对每个文件进行布尔检查,以确认它是否实际上是一个压缩文件夹。 The twist is that Excel files are able to be opened like a compressed folder (and have docProps, xl, _rels in it.)不同之处在于 Excel 文件可以像压缩文件夹一样打开(并且其中包含 docProps、xl、_rels。)

I've been unsuccessfully trying get-childitem and Get-Content.我一直没有成功尝试 get-childitem 和 Get-Content。 Is there a way to do a "test" on a file that returns true if it is actually a zip file?有没有办法对返回 true 的文件进行“测试”,如果它实际上是一个 zip 文件?

The Carbon Powershell module includes a cmdlet Test-ZipFile which will tell you if it's a zipfile or not. Carbon Powershell模块包含一个cmdlet Test-ZipFile ,它会告诉您它是否是zipfile。

If you can't use that module, you can look at the file header . 如果您无法使用该模块,则可以查看文件头 This is a little ugly (short on time) but works: 这有点难看(时间紧迫)但有效:

$contents = [string](get-content -raw -Encoding Unknown -path $filepath).ToCharArray();

[convert]::tostring([convert]::toint32($contents[0]),16);

The output is 4b50 for a file which is known to be a ZIP file, which matches the first two bytes of the signature, reversed. 对于一个已知为ZIP文件的文件,输出为4b50 ,该文件与签名的前两个字节相匹配,相反。

Longer term, make the vendor fix their system to provide more information about the files. 从长远来看,让供应商修复他们的系统以提供有关文件的更多信息。 Especially if they're the type you want. 特别是如果它们是你想要的类型。

If you need to distinguish between Excel (2007+ ) and true ZIP files, without having an extension, you're stuck - as you already know, you can just rename the .xlsx file to .zip and it'll open like any other ZIP file - there's nothing to distinguish. 如果您需要区分Excel(2007+)和真正的ZIP文件,而没有扩展名,那么您就会陷入困境 - 正如您所知,您可以将.xlsx文件重命名为.zip,它将像其他任何文件一样打开ZIP文件 - 没有什么可以区分的。

I ended up doing something like this, hopefully someone finds it useful: 我最终做了这样的事情,希望有人发现它很有用:

$ErrorStatus=Start-Process -FilePath $env:7ZipExe -ArgumentList " x $FullFileName -o$env:ProcessingFolder"  -passthru -Wait

If (($ErrorStatus.ExitCode -eq 0) -or ($ErrorStatus.ExitCode -eq $null))
{
    $FileContents=get-childitem -path $FullFileName
    #_rels is a folder in a Word or Excel file when you open it with 7-zip. If it is able to be opened with 7-zip and 
    #  doesn't have that folder, consider the file to be a zip file.
    if (!($FileContents -like "*rels*"))
    {   
        if (!($FileContents -like "*xl*") -and (!($FullFileName.ToLower().EndsWith('.xlsx'))))
        {
            Rename-Item $FullFileName "$FullFileName.xlsx"
        }
        elseif (!($FileContents -like "*word*") -and (!($FullFileName.toLower().EndsWith('.docx')))-and (!($FullFileName.toLower().EndsWith('.xlsx'))))
        {
            Rename-Item $FullFileName "$FullFileName.docx"
        }
    }
    else
    {
        If (!($FileName.ToLower().EndsWith(".zip")))
        {
            Rename-Item $FullFileName "$FullFileName.zip"
            Add-Content $env:LogReportFile "$(Get-Date) - $FileName was a zip file. Added extension."
        }
    }
}

Following on the answer above, I ran into some issues with the script posted due to the '!'按照上面的答案,由于“!”,我在发布的脚本中遇到了一些问题。 char's in the If statements, here's what worked for me,字符在 If 语句中,这对我有用,

My usecase was recovering DOCX and XLSX files after a friend's hard drive got corrupted due to a power loss and they had a bunch of CHK files, which 'unchk' utility renamed to Zip files.我的用例是在朋友的硬盘因断电而损坏后恢复 DOCX 和 XLSX 文件,他们有一堆 CHK 文件,“unchk”实用程序重命名为 Zip 文件。

Note the temp save directory mentioned here - this process will need to extract your zip's to read the contents, so this code expects a folder of zips to run thru, then extracts each one into its own folder in a seperate directory for temp files.请注意此处提到的临时保存目录 - 此过程需要解压缩您的 zip 以读取内容,因此此代码需要运行一个 zip 文件夹,然后将每个文件夹解压缩到临时文件的单独目录中的自己的文件夹中。

    $FolderPath = "C:\FOUND.001\"

Get-ChildItem $FolderPath -Filter *.zip | 
Foreach-Object {
#Write-Output $_.FullName

#If ($_.FullName -eq "C:\FOUND.001\FILE3640.zip"){ TEST LINE, REMOVED AFTER SUCCESSFULLY WORKING ON 1 FILE OF THOUSANDS...
    $FullFileName = $_.FullName
    Write-Output $FullFileName
    $ZipName = $_.BaseName
    

    $TempSaveDirectory = "C:\RecoveryResults\$ZipName"
    Write-Output "Creating $TempSaveDirectory"
    #Make a directory to hold zip contents
    New-Item $TempSaveDirectory -ItemType directory
    
$ErrorStatus=Start-Process -FilePath "C:\Program Files\7-Zip\7z.exe" -ArgumentList " x $FullFileName -o$TempSaveDirectory"  -passthru -Wait

If (($ErrorStatus.ExitCode -eq 0) -or ($ErrorStatus.ExitCode -eq $null))
{
    $FileContents=get-childitem -path $TempSaveDirectory
    #_rels is a folder in a Word or Excel file when you open it with 7-zip. If it is able to be opened with 7-zip and 
    #  doesn't have that folder, consider the file to be a zip file.
    if ($FileContents -like "*rels*")
    {   
    write-output "Found rels folder"
        if ($FileContents -like "*xl*")
        {
            Rename-Item $FullFileName "$FullFileName.xlsx"
            Write-Output "Renamed $FullFileName To Excel"
        }
        elseif ($FileContents -like "*word*")
        {
            Rename-Item $FullFileName "$FullFileName.docx"
            Write-Output "Renamed $FullFileName To Word Doc"
        }
    }
    else
    {
        If (!($FullFileName.ToLower().EndsWith(".zip")))
        {
            
        }
    }
}
}

#}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM