Expand a zip archive (platform agnostic)
tony
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
// 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
Forum
Support
Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More
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:
February 22, 2020 at 02:39 pm - Permalink
In reply to Note, this: StringByKey(… by ilavsky
Thanks, I've edited the code snippet to use your suggested method.
February 24, 2020 at 12:52 pm - Permalink
In reply to Thanks, I've edited the code… by tony
And edited again to include a fix from Jim Prouty. So Windows 8.0 is actually version 6.2 - go figure!
April 8, 2020 at 04:50 am - Permalink
FYI, Igor 9, in beta soon, has a new built-in UnzipFile operation that can unzip a file.
April 8, 2020 at 07:19 am - Permalink
edited snippet to add quotes around mac paths.
January 26, 2021 at 02:57 am - Permalink
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
#elif MACINTOSH
#else
Abort "New platform"
#endif
which does the job
January 26, 2021 at 02:24 pm - Permalink
In reply to I seemed to have missed the… 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" :)
January 26, 2021 at 11:54 pm - Permalink
> 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.
January 27, 2021 at 07:46 am - Permalink