Expand a zip archive (platform agnostic)

Function to expand a zip archive. Works on Mac and on Windows 8 and later.

See also Andrew Nelson's ZIP XOP and Jan Ilavsky's code snippet.

// utility function, inflates a zip archive
// verbose=1 to print output from executescripttext
function unzipArchive(string archivePathStr, string unzipPathStr, [int verbose])
    verbose = ParamIsDefault(verbose) ? 1 : verbose    
    string validExtensions = "zip;" // set to "" to skip check
    string msg, unixCmd, cmd
       
    GetFileFolderInfo /Q/Z archivePathStr

    if (V_Flag || V_isFile==0)
        printf "Could not find file %s\r", archivePathStr
        return 0
    endif

    if (ItemsInList(validExtensions) && FindListItem(ParseFilePath(4, archivePathStr, ":", 0, 0), validExtensions, ";", 0, 0) == -1)
        printf "%s doesn't appear to be a zip archive\r", ParseFilePath(0, archivePathStr, ":", 1, 0)
        return 0
    endif
   
    if (strlen(unzipPathStr) == 0)
        unzipPathStr = SpecialDirPath("Desktop",0,0,0) + ParseFilePath(3, archivePathStr, ":", 0, 0)
        sprintf msg, "Unzip to %s:%s?", ParseFilePath(0, unzipPathStr, ":", 1, 1), ParseFilePath(0, unzipPathStr, ":", 1, 0)
        DoAlert 1, msg
        if (v_flag == 2)
            return 0
        endif
    else
        GetFileFolderInfo /Q/Z unzipPathStr
        if (V_Flag || V_isFolder==0)
            sprintf msg, "Could not find unzipPathStr folder\rCreate %s?", unzipPathStr
            DoAlert 1, msg
            if (v_flag == 2)
                return 0
            endif
        endif
    endif
   
    // make sure unzipPathStr folder exists - necessary for mac
    NewPath /C/O/Q acw_tmpPath, unzipPathStr
    KillPath /Z acw_tmpPath

    if (stringmatch(StringByKey("OS", IgorInfo(3))[0,2],"Win")) // Windows
        // The following works with .Net 4.5, which is available in Windows 8 and up.
        // current versions of Windows with Powershell 5 can use the more succinct PS command
        // 'Expand-Archive -LiteralPath C:\archive.zip -DestinationPath C:\Dest'
        string strVersion = StringByKey("OSVERSION", IgorInfo(3))
        variable WinVersion = str2num(strVersion) // turns "10.1.2.3" into 10.1 and 6.23.111 into 6.2 (windows 8.0)
        if (WinVersion<6.2)
            Print "unzipArchive requires Windows 8 or later"
            return 0
        endif
       
        archivePathStr = ParseFilePath(5, archivePathStr, "\\", 0, 0)
        unzipPathStr = ParseFilePath(5, unzipPathStr, "\\", 0, 0)
        cmd = "powershell.exe -nologo -noprofile -command \"& { Add-Type -A 'System.IO.Compression.FileSystem';"
        sprintf cmd "%s [IO.Compression.ZipFile]::ExtractToDirectory('%s', '%s'); }\"", cmd, archivePathStr, unzipPathStr
    else // Mac
        sprintf unixCmd, "unzip '%s' -d '%s'", ParseFilePath(5, archivePathStr, "/", 0,0), ParseFilePath(5, unzipPathStr, "/", 0,0)
        sprintf cmd, "do shell script \"%s\"", unixCmd
    endif
   
    ExecuteScriptText /B/UNQ/Z cmd
    if (verbose)
        Print S_value // output from executescripttext
    endif
   
    return (v_flag == 0)
end

 

Note, this: StringByKey("OSVERSION", igorinfo(3)) returns for Windows 10 something like 6.3.18363, not user friendly 8 or 10. This seems to work and returns either 8 or 10 as expected:

variable WinVersion=str2num(StringByKey("OS", igorinfo(3))[7,12])	

FYI, Igor 9, in beta soon, has a new built-in UnzipFile operation that can unzip a file.

I seemed to have missed the windows version discussion. "Predefined Global Symbols" says that MACINTOSH and WINDOWS are compile time defines for the platforms. So you can do

#ifdef WINDOWS

#elif MACINTOSH

#else
  Abort "New platform"
#endif

which does the job

In reply to by thomas_braun

@thomas_braun

Yes, #ifdef WINDOWS is an arguably better alternative to other methods of checking the platform. The issue with the original version was the check for windows version >=8, which can be done with a call to IgorInfo, but you have to be aware that window 8 self identifies as windows 6.2. AFAIK, the code above does what it should. My recent edit was a fix for mac paths that have spaces.

I see that you live in hope of a port to a "new platform" :)

 

> I see that you live in hope of a port to a "new platform" :)

Yes! And I also learned that future proofing code can avoid hours of debugging.

Forum

Support

Gallery

Igor Pro 9

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More