source

Powershell에서 Native .tar 추출

nicesource 2023. 8. 17. 21:26
반응형

Powershell에서 Native .tar 추출

나는 있습니다.tar.gz추출해야 하는 파일입니다.▁withzip▁the▁gun로 건집 비트를 했습니다.GzipStream의 입니다.System.IO.Compression하지만 그 네임스페이스에서 타르볼을 다룰만한 것을 찾을 수 없었습니다.우리가 할 수 있는 일이.tarPowershell에 있는 파일들?Powershell 스크립트에서 이러한 함수/메소드/객체 구성/시스템 바이너리를 호출할 수 있는 것만이 중요합니다. 실제로 Powershell로 작성할 필요는 없습니다. (중요한 경우 64비트 윈도우 10을 사용합니다.)

추신: "7zip 사용"이라고 말하지 마십시오. 그것은 네이티브가 아닙니다.

는 어요믿을 믿습니다.tar는 이 게시물이 게시된 이후 Windows 10에 기본 기능으로 추가되었습니다.

명령 프롬프트 또는 Windows 10의 PowerShell에서 실행할 수 있습니다.

tar -xvzf .\whatever.tar.gz

로 고는 다음과 ..\의 사용에 의해 자동 압축 해제된 후 추가되었습니다.tabPowerShell에서, 하지만 그것 없이는 작동할 수 있다고 생각합니다.

이 기능과 유닉스 구현 사이에는 몇 가지 근본적인 차이점이 있을 수 있지만(결국 Windows에 있기 때문에) 저에게는 효과가 있었습니다.

2019년 업데이트:

다른 답변에서 지적했듯이 BSD tar는 2018년에 내장 명령어로 Windows 10에 추가되었습니다.이 대답은 이전 버전의 Windows(윈도우)를 지원해야 하는 경우에도 적용할 수 있습니다.


윈도우 10은 2018년 이전에는 기본적으로 tar 파일 추출을 지원하지 않았습니다.

Windows 10(초기 버전)을 위한 빠르고 간편한 솔루션

스크립트에 활성 인터넷 연결에 대한 액세스 권한이 있을 것으로 예상할 수 있는 경우 기본 패키지 관리자를 사용하여 7Zip 지원을 받을 수 있습니다.이 솔루션:

  • 스크립트를 통해 완전히 자동화됨(사용자 작업 필요 없음)
  • 관리자 권한이 필요하지 않음
  • 7Zip 지원 모듈을 아직 사용할 수 없는 경우에만 설치합니다.

여기 있습니다.

function Expand-Tar($tarFile, $dest) {

    if (-not (Get-Command Expand-7Zip -ErrorAction Ignore)) {
        Install-Package -Scope CurrentUser -Force 7Zip4PowerShell > $null
    }

    Expand-7Zip $tarFile $dest
}

사용 방법:

Expand-Tar archive.tar dest

이는 작업을 수행하지만 클라이언트 시스템을 지속적으로 변경합니다.더 나은 솔루션이 있지만 조금 더 관련된 솔루션이 있습니다.

더 나은 해결책

더 나은 솔루션은 7Zip4를 번들로 제공하는 것입니다.스크립트와 함께 PowerShell에 액세스할 수 있습니다.이 솔루션:

  • 스크립트를 통해 완전히 자동화됨(사용자 작업 필요 없음)
  • 관리자 권한이 필요하지 않음
  • 클라이언트 시스템에 소프트웨어를 설치하지 않음
  • 인터넷 연결이 필요하지 않음
  • 이전 버전의 Windows에서 작동해야 함

7Zip4 사본 다운로드PowerShell 패키지

LGPL-2.1 라이선스로 배포되므로 패키지를 제품과 함께 묶어도 괜찮습니다.GNU 라이센스 제품의 소스 코드에 대한 액세스 권한을 제공해야 하므로 문서에 패키지를 사용하고 링크를 제공한다는 내용의 참고 사항을 추가해야 합니다.

Save-Module -Name 7Zip4Powershell -Path .

그러면 현재 디렉터리로 다운로드됩니다.Windows 10에서 이 작업을 수행하는 것이 가장 쉽지만 위의 링크에서 이전 버전의 Windows에서 PowerShell Gallery를 시스템에 추가하는 방법에 대한 지침이 나와 있습니다.

tar 파일을 추출해야 할 때 모듈 가져오기

첫 번째 솔루션을 기반으로 이를 수행할 수 있는 방법을 보여주기 위해 간단한 기능을 만들었습니다.

function Expand-Tar($tarFile, $dest) {

    $pathToModule = ".\7Zip4Powershell\1.9.0\7Zip4PowerShell.psd1"

    if (-not (Get-Command Expand-7Zip -ErrorAction Ignore)) {
        Import-Module $pathToModule
    }

    Expand-7Zip $tarFile $dest
}

$pathToModule스크립트가 실행될 때 번들 모듈이 실제로 저장되는 위치로 이동하지만, 아이디어가 있어야 합니다.위의 두 코드 블록을 PowerShell 창에 붙여넣고 작업을 수행할 수 있도록 이 예제를 작성했습니다.Expand-Tarcdlet:

Expand-Tar archive.tar dest

가능한 해결 방법:

윈도우 10을 실행하고 .curl+tar파워셸 내에서 하지만 지원이 부족했습니다.운 좋게도, 윈도우 10에서 Ubuntu bash를 실행했습니다.curl그리고.tar사전 설치되어 해당 환경에서 실행된 후 다운로드 및 압축 해제 후 Powershell로 다시 전환하여 작업을 계속했습니다.

또는 아래 설명에서 @Don Cruickshank가 언급한 대로 PowerShell 내에서 7zip 지원을 직접 설치할 수 있습니다.Install-Package 7Zip4Powershell.Expand-7zip은 tar.cmdlet tar와 여러 형식을 합니다.

이러한 해결 방법으로 특정 문제를 해결할 수는 없지만 Windows(윈도우)에 남아 있는 문제의 경우 유용할 수 있습니다.

로 윈도우 은 2017년에 출시되었습니다.tar은 할 수 .exepowershell맘에 들다tar -xkf $archivePath -C $outDir 은혹더것은에서 더 .pwsh.

시간이 좀 걸렸지만 제가 만든 해결책은 이렇습니다.기본적으로 TAR은 매우 간단한 형식이지만 처리하는 데는 몇 줄의 코드가 필요합니다.

Function ConvertTo-ByteString
{
    Param(
    [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True )][byte[]]$Buffer
    )

    # Note: Codepage 28591 returns a 1-to-1 char to byte mapping
    $Encoding = [System.Text.Encoding]::GetEncoding(28591)
    #$BinaryText = [System.Text.Encoding]::Convert('ascii', '28591', $Buffer)
    $BinaryText = [System.Text.Encoding]::ASCII.GetString($Buffer)
    $BinaryText = $BinaryText.Trim(0)
    $BinaryText = $BinaryText.Trim(32)
    $BinaryText = $BinaryText.Trim(0)
    $BinaryText = $BinaryText.Trim(32)
    return $BinaryText
}

Function New-USTARHeaderObject
{
    #Write-Host('[New-USTARHeaderObject]','Creating new header object') -ForegroundColor Cyan
    $Header = New-Object -Type PSObject
    $Header | Add-Member -MemberType NoteProperty -Name name -Value $null
    $Header | Add-Member -MemberType NoteProperty -Name mode -Value $null
    $Header | Add-Member -MemberType NoteProperty -Name uid -Value $null
    $Header | Add-Member -MemberType NoteProperty -Name gid -Value $null
    $Header | Add-Member -MemberType NoteProperty -Name size -Value $null
    $Header | Add-Member -MemberType NoteProperty -Name mtime -Value $null
    $Header | Add-Member -MemberType NoteProperty -Name cksum -Value $null
    $Header | Add-Member -MemberType NoteProperty -Name typeflag -Value $null
    $Header | Add-Member -MemberType NoteProperty -Name linkname -Value $null
    $Header | Add-Member -MemberType NoteProperty -Name magic -Value $null
    $Header | Add-Member -MemberType NoteProperty -Name version -Value $null
    $Header | Add-Member -MemberType NoteProperty -Name uname -Value $null
    $Header | Add-Member -MemberType NoteProperty -Name gname -Value $null
    $Header | Add-Member -MemberType NoteProperty -Name devmajor -Value $null
    $Header | Add-Member -MemberType NoteProperty -Name devminor -Value $null
    $Header | Add-Member -MemberType NoteProperty -Name prefix -Value $null

    return $Header
   
}

Function Fill-USTARHeaderObject
{
    Param(
    [Parameter(Mandatory=$True)][PSObject]$Header,
    [Parameter(Mandatory=$True)][byte[]]$Buffer
    )
    
    #Write-Host('[Fill-USTARHeaderObject]','Filling header object with bytes') -ForegroundColor Cyan
    $Header.name = [string](ConvertTo-ByteString $Buffer[0..99])
    $Header.mode = ConvertTo-ByteString $Buffer[100..107]
    $Header.uid = ConvertTo-ByteString $Buffer[108..115]
    $Header.gid = ConvertTo-ByteString $Buffer[116..123]
    $Header.size = ConvertTo-ByteString $Buffer[124..135]
    $Header.mtime = ConvertTo-ByteString $Buffer[136..147]
    $Header.cksum = ConvertTo-ByteString $Buffer[148..155]
    $Header.typeflag = ConvertTo-ByteString $Buffer[156]
    $Header.linkname = ConvertTo-ByteString $Buffer[157..256]
    $Header.magic = ConvertTo-ByteString $Buffer[257..262]
    $Header.version = ConvertTo-ByteString $Buffer[263..264]
    $Header.uname = ConvertTo-ByteString $Buffer[265..296]
    $Header.gname = ConvertTo-ByteString $Buffer[297..328]
    $Header.devmajor = ConvertTo-ByteString $Buffer[329..336]
    $Header.devminor = ConvertTo-ByteString $Buffer[337..344]
    $Header.prefix = ConvertTo-ByteString $Buffer[345..499]
}


Function Check-IsUSTARHeaderObject
{
    Param(
    [Parameter(Mandatory=$True, Position = 0, ValueFromPipeline = $True)][PSObject]$Header
    )
    $Regex_Numeric = [regex]"^\d+$"
    #Write-Host('[Check-IsUSTARHeaderObject]','Checking if object is actual header') -ForegroundColor Cyan

    #Write-Host("[Mode    ]",$Header.mode,($Regex_Numeric.Matches($Header.mode).Success)) -ForegroundColor Magenta
    #Write-Host("[Size    ]",$Header.size,($Regex_Numeric.Matches($Header.size).Success)) -ForegroundColor Magenta
    #Write-Host("[MTime   ]",$Header.mtime,($Regex_Numeric.Matches($Header.mtime).Success)) -ForegroundColor Magenta
    #Write-Host("[CKSum   ]",$Header.cksum,($Regex_Numeric.Matches($Header.cksum).Success)) -ForegroundColor Magenta
    #Write-Host("[TypeFlag]",$Header.typeflag,($Regex_Numeric.Matches($Header.typeflag).Success)) -ForegroundColor Magenta
    #Write-Host("[Magic   ]",$Header.magic,($Header.magic -eq 'ustar')) -ForegroundColor Magenta

    if (
        ($Regex_Numeric.Matches($Header.mode).Success) -and
        ($Regex_Numeric.Matches($Header.size).Success) -and
        ($Regex_Numeric.Matches($Header.mtime).Success) -and
        ($Regex_Numeric.Matches($Header.cksum).Success) -and
        ($Regex_Numeric.Matches($Header.typeflag).Success) -and
        ($Header.magic -eq 'ustar')
    )
    {
        #Write-Host('[Check-IsUSTARHeaderObject]','TRUE') -ForegroundColor DarkCyan
        return $true
    } else {
        #Write-Host('[Check-IsUSTARHeaderObject]','FALSE') -ForegroundColor DarkCyan
        return $false
    }
}


Function UnTar-File
{
    Param(
    [Parameter(Mandatory=$True)][String]$Source,
    [Parameter(Mandatory=$False)][String]$Destination
    )
   
    #$Source = 'D:\temp\th-dfbase-blacklist.tar'
    $SourceBaseName = (Get-Item $Source).BaseName
    Write-Host('[UnTar-File]','Setting Source',$Source) -ForegroundColor Cyan

    #if destination parameter not given
    if ($Destination -eq "")
    {
        $SourcePath = Split-Path $Source
        $OutFolder = Join-Path -Path $SourcePath -ChildPath $SourceBaseName
    }
    else
    {
        $OutFolder = Join-Path -Path $Destination -ChildPath $SourceBaseName
    }

    Write-Host('[UnTar-File]','Destination Folder',$OutFolder) -ForegroundColor DarkCyan

    $FileStream = New-Object System.IO.FileStream $Source, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read)

    $BufferSize = 512
    $Buffer = New-Object byte[]($BufferSize)

    Write-Host('[UnTar-File]','Reading Source by', $BufferSize,'bytes') -ForegroundColor Cyan
    while($true)
    {
    
        $read = $FileStream.Read($Buffer, 0, $BufferSize)
        #Write-Host($read) -ForegroundColor Cyan

        if ($read -le 0){break}

        #Try Header
        $Header = New-USTARHeaderObject
        Fill-USTARHeaderObject -Header $Header -Buffer $Buffer

        #if header section
        if (Check-IsUSTARHeaderObject($Header))
        {
            $ItemPath = [IO.Path]::Combine($Header.prefix, $Header.name)
            $ItemPath = $ItemPath.Replace('/','\')

            #if folder type
            if ($Header.typeflag -eq '5')
            {
                $FolderPath = Join-Path -Path $OutFolder -ChildPath $ItemPath
                Write-Host('[UnTar-File]','Creating Folder',$FolderPath) -ForegroundColor Yellow
                New-Item -Path $FolderPath -ItemType Directory -Force | Out-Null
            }
            #if file type
            else
            {
                $FilePath = Join-Path -Path $OutFolder -ChildPath $ItemPath
                Write-Host('[UnTar-File]','Creating File',$FilePath) -ForegroundColor DarkYellow
                if ($OutputFile -ne $null)
                {
                    $OutputFile.Close()
                }
                $OutputFileInfo = New-Object PSObject
                $OutputFileInfo | Add-Member -MemberType NoteProperty -Name name -Value $Header.name
                $OutputFileInfo | Add-Member -MemberType NoteProperty -Name path -Value (Split-Path -Path $FilePath)
                $OutputFileInfo | Add-Member -MemberType NoteProperty -Name size -Value ([Convert]::ToInt32($Header.size, 8))
                $OutputFileInfo | Add-Member -MemberType NoteProperty -Name left2write -Value ([Convert]::ToInt32($Header.size, 8))
                $OutputFileInfo | Add-Member -MemberType NoteProperty -Name mtime -Value ([Convert]::ToInt32($Header.mtime, 8))
                $OutputFile = New-Object System.IO.FileStream $FilePath, ([IO.FileMode]::Create), ([IO.FileAccess]::Write), ([IO.FileShare]::None)
            }
        }
        #if data section
        else
        {
            if ($OutputFileInfo.left2write -ge $BufferSize)
            {
                $WriteSize = $read
            } else {
                $WriteSize = $OutputFileInfo.left2write
            }
            $OutputFile.Write($Buffer, 0, $WriteSize)
            $OutputFileInfo.left2write = ($OutputFileInfo.left2write - $WriteSize)
        }
    }
    $FileStream.Close()
    if ($OutputFile -ne $null)
    {
        $OutputFile.Close()
    }
}


UnTar-File -Source $Tar

그래서 제가 이것을 물어본 지 11일이 지났고 일반적인 합의는 "아니요, 바닐라 윈도우 설치에는 타르 추출을 '당신을 위해' 처리할 수 있는 네이티브 도구가 없습니다."입니다.

이 대답은 마티아스 R에서 나왔습니다. JensenTesellating Heckler는 둘 다 논평 외의 답변을 거부했습니다(전체 Windows 시스템 아키텍처에 대한 깊은 지식 없이는 "아니오"라고 말하고 싶지 않아서 그런 것 같습니다.).

설치할 수 있는 스크립트, 클래스 및 프로그램은 확실히 있지만 "네이티브"는 없습니다.

이 스니펫은 계속 작동합니다. 이 스니펫에서 사용하는 것이 설치되어 있지 않은 것 같습니다.이 타르를 뽑아내는 방법을 찾아야 해요

Function DeGZip-File{
    Param(
        $infile
        )
    $outFile = $infile.Substring(0, $infile.LastIndexOfAny('.'))
    $input = New-Object System.IO.FileStream $inFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read)
    $output = New-Object System.IO.FileStream $outFile, ([IO.FileMode]::Create), ([IO.FileAccess]::Write), ([IO.FileShare]::None)
    $gzipStream = New-Object System.IO.Compression.GzipStream $input, ([IO.Compression.CompressionMode]::Decompress)

    $buffer = New-Object byte[](1024)
    while($true){
        $read = $gzipstream.Read($buffer, 0, 1024)
        if ($read -le 0){break}
        $output.Write($buffer, 0, $read)
        }

    $gzipStream.Close()
    $output.Close()
    $input.Close()
}

$infile='D:\[Directory]\[File].tar.gz'

DeGZip-File $infile 

다음은 PowerShell 스크립트의 일부입니다.

try
{
    Add-Type -AssemblyName "ICSharpCode.SharpZLib"

    $file = [IO.File]::OpenRead($gzArchiveName)
    $inStream=New-Object -TypeName ICSharpCode.SharpZipLib.GZip.GZipInputStream $file
    $tarIn = New-Object -TypeName ICSharpCode.SharpZipLib.Tar.TarInputStream $inStream
    $archive = [ICSharpCode.SharpZipLib.Tar.TarArchive]::CreateInputTarArchive($tarIn)
    $archive.ExtractContents($WORKDIR)
}
finally
{
    $archive.Close
}

TarTool.exe 유틸리티의 코드에 해당합니다.

언급URL : https://stackoverflow.com/questions/38776137/native-tar-extraction-in-powershell

반응형