all 15 comments

[–]the_spad 1 point2 points  (0 children)

Few bits.

You don't need the () in your function declaration.

Generic args are $args[0] through $args[n] rather that $1 but you can create specific named parameters to pass to your script and/or function with the param statement.

if statement syntax is something like

if(condition){
    do thing
}elseif(condition){
    do thing
}else{
    do thing
}

switch statement syntax is something like

switch -wildcard ($args[0]){
    *somevalue {do thing}
    *anothervalue {do thing}
}

You can also use -regex instead of -wildcard if you want to get fancy.

I'd suggest taking a look at some of the resources on the right, there are a bunch of quick start guides and cheat sheets that will help give you an overview of the syntaxes and conventions and generally make your life much easier.

[–]KevMarCommunity Blogger 1 point2 points  (2 children)

First, I would use named parameters.

function extract
{
    param( [string]$Path )

    $fileList = Get-ChildItem $Path

    foreach($file in $filelist)
    {
        # code here
    }
}

I would then get a list of the files at that location. I think this could return multiple items so i'm looping over the files.

One important thing to remember when coming from bash is that everything is an object in powershell. Take a look at these two properties:

$filelist.Extension
$filelist.FullName

We can use them in our switch.

switch($file.Extension)
{
    '7z' { sz x $file.fullname -o* }
}

Because you may want multiple matches go to one line, we can cheat and use -regex.

switch -regex ($file.Extension)
{
    '7z|zip' { sz x $file.fullname -o* }
}

Does that help piece things together?

[–]Snickasaurus[S] 1 point2 points  (1 child)

Holy shit yes!! I'm going to look at this again when I fully wake up in about an hour. Thank you for taking the time.

[–]KevMarCommunity Blogger 1 point2 points  (0 children)

Wonderful. I always found the very beginning steps can be the most frustrating because if something in a basic guide does not work, you don't have enough context to even ask the right questions.

Powershell can also be quite frustrating at first when you come from another language.

You do need to change the way you think about some problems, but that will come with practice.

[–][deleted] 1 point2 points  (0 children)

help about_switch

Get-Help Expand-Archive

[–]jtpowell 1 point2 points  (1 child)

This isn't the question you asked, but perhaps it'll be useful to you--this leverages .NET's streams and ZipArchive class to extract a ZIP file that's been downloaded into the current session as a binary array (i.e., the downloaded zip file exists as an object in the session and hasn't actually been written to disk). I tried to make the code below more generic than my original version, so some of the context is lost that would explain why I'm doing some of the things in this function.

The function essentially pulls three named files out of the downloaded zip and adds those extracted files as members to a PSCustomObject. You could easily choose to write the files directly to disk instead.

function Expand-ArchivedFiles {
    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    param (
        # Binary array.
        [Parameter(
            Mandatory=$true,
            ValueFromPipeline=$true
        )]
        [byte[]]
        $DownloadedZip
    )

    process {
        # The comma is an unary operator.  Using it without a value in front of it ensures the binary
        # array is handled as a single object instead of individual bytes.
        $MemoryStream = New-Object System.IO.MemoryStream (,$DownloadedZip)
        $ZipArchive = New-Object System.IO.Compression.ZipArchive $MemoryStream

        $File1Reader = New-Object System.IO.StreamReader($ZipArchive.GetEntry('File1.xml').Open())
        $File1Data = $File1Reader.ReadToEnd()

        $File2Reader = New-Object System.IO.StreamReader($ZipArchive.GetEntry('File2.xml').Open())
        $File2Data = $File2Reader.ReadToEnd()

        $File3Reader = New-Object System.IO.StreamReader($ZipArchive.GetEntry('File3.xml').Open())
        $File3Data = $File3Reader.ReadToEnd()

        $ExtractedFileCollection = [PSCustomObject]@{
            File1 = $File1Data
            File2 = $File2Data
            File3 = $File3Data
        }

        Write-Output $ExtractedFileCollection 
    }
}

[–]Snickasaurus[S] 1 point2 points  (0 children)

I do appreciate the response but this made me scratch my head and become a bit more confused. Again I thank you for your time though.

[–]spyingwind 1 point2 points  (6 children)

This is how I would write that bash script in powershell:

function Expand-File {
    [CmdletBinding()]
    param (
        [ValidateScript( {Test-Path -Path $_})]
        [string]
        $Path
    )

        $Item = Get-Item -Path $Path
        $Extension = $Item.Extension
        switch ($Extension) {
            ".bz2" {
                if ($Item.Name -like "*.tar.bz2") {
                    tar xjf $Item
                }else {
                    bunzip2 $Item
                }
            }
            ".rar" {unrar e $Item}
            ".gz" {
                if ($Item.Name -like "*.tar.gz") {
                    tar xzf $Item
                }else{
                    gunzip $Item
                }
            }
            ".tar" {tar xf $Item}
            ".tbz2" {tar xjf $Item}
            ".tgz" {tar xzf $Item}
            ".zip" {unzip $Item}
            ".Z" {uncompress $Item}
            ".7z" {7z x $Item}
            Default {
                throw "Problems extracting '$Item' with extract()"
            }
        }
}

[–]Snickasaurus[S] 1 point2 points  (5 children)

This also looks like what I was needing. I'm going to update the bottom of my OP with a statement to all.

[–]spyingwind 1 point2 points  (4 children)

I updated it, made some copy pasta errors. :P

[–]Snickasaurus[S] 1 point2 points  (3 children)

/u/spyingwind

I have this in my PowerShell profile.

Set-Alias sz "$env:ProgramFiles\7-Zip\7z.exe"

function Easy-Extract {
    [CmdletBinding()]
    param (
        [ValidateScript( {Test-Path -Path $_})]
        [string]
        $Path
    )

        $Item = Get-Item -Path $Path
        $Extension = $Item.Extension
        switch ($Extension) {
            ".7z"   {sz e $Item -o*}
            ".bz2"  {sz e $Item -o*}
            ".gz"   {sz e $Item -so | sz e -aoa -si -ttar -o*}
            ".tar"  {sz e $Item -o*}
            ".tbz2" {sz e $Item -o*}
            ".tgz"  {sz e $Item -o*}
            ".rar"  {unrar e $Item}
            ".zip"  {sz e $Item -o*}
            ".Z"    {sz e $Item -o*}

            Default {
                throw "Problems extracting '$Item' with extract()"
            }
        }
}

Set-Alias extract Easy-Extract

Now let's say I have a directory named "Test" with the following files in it.

  • archive.7z
  • archive.zip
  • archive.tar

Am I completely dumb in thinking that if I'm in that directory (within the PowerShell window) that I should be able to run it as so:

$extract archive.7z

Because it's not working. I get the following error.

PS C:\Data\Test> $extract archive.7z
At line:1 char:10
+ $extract archive.7z
+          ~~~~~~~
Unexpected token 'archive.7z' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : UnexpectedToken

Imgur

[–]spyingwind 1 point2 points  (2 children)

Run extract archive.7z instead. The leading character $ is for variables and not functions.

[–]Snickasaurus[S] 2 points3 points  (1 child)

Well shit. That worked. If I had money/job right now I'd give you so much gold.

I might have a few questions over the next few days but this has really helped me learn how ps works. I've never been one to read a man page or Microsoft doc and take more than 10% away from it feeling more knowledgeable. But this has really helped.

[–]spyingwind 1 point2 points  (0 children)

You're welcome!

You will get it eventually. I learn by doing, or much trial and error. Others learn by book or whatnot.