December 22, 201015 yr Hi all, I'm a "noob" at ScriptMaster and have seen how to zip a selected file with the example code. Does anyone have a good example of how to zip an entire directory/folder? TIA, Denis
December 22, 201015 yr The current module does not have the ability to zip a directory. If you are interested in having us make you a module to do this please send an email to [email protected].
December 24, 201015 yr Or use this // ZipDir ( fm_dirIn ; fm_fileOut ) // 10_12_23_JR WORKING // v1.0 // adds all of tree from starting directory to zip file // adapted from Solomon Duskis, http://www.jroller.com import java.io.File import java.io.FileInputStream import java.io.FileOutputStream import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream try { topDir = new File(fm_dirIn) zipOut = new ZipOutputStream ( new FileOutputStream(fm_fileOut) ); topDirLength = topDir.absolutePath.length() topDir.eachFileRecurse{ file -> relPath = file.absolutePath.substring(topDirLength).replace('\\', '/') if ( file.isDirectory() && !relPath.endsWith('/')){ relPath += "/" } entry = new ZipEntry(relPath) entry.time = file.lastModified() zipOut.putNextEntry(entry) if( file.isFile() ){ zipOut << new FileInputStream(file) } } zipOut.close() } catch (Exception e) { e.printStackTrace() } return true
December 25, 201015 yr And if you want a full recursive unzip try this // unZipDir ( fm_dirOut ; fm_fileIn ) // 10_12_23_JR WORKING // v1.1 // unzips nested files from zip file // adapted from jsshah, http://www.stackoverflow.com import java.io.FileInputStream import java.io.FileOutputStream import java.util.zip.ZipInputStream try { int BUFFER_SIZE = 2048 fis = new FileInputStream(new File(fm_fileIn)) zis = new ZipInputStream(new BufferedInputStream(fis)) while((entry = zis.getNextEntry()) != null) { outFile = fm_dirOut + entry.getName() name = entry.getName() if (name.endsWith("/")) { newDirs = new File(fm_dirOut + name) if(!newDirs.mkdirs() && !newDirs.isDirectory()) { // dir creation failed return ERROR } //newDirs.mkdirs() } else { byte[] data = new byte[bUFFER_SIZE]; fos = new FileOutputStream(outFile) dest = new BufferedOutputStream(fos, BUFFER_SIZE) while((count = zis.read(data, 0, BUFFER_SIZE)) != -1) { dest.write(data, 0, count) } //end while //close the output streams dest.flush() dest.close() } //end while } //finished with all the files, so close the zip zis.close() } catch(Exception e) { e.printStackTrace() return false } return true
December 28, 201015 yr Author John, This works beautifully for exactly what I was looking for. Thanks very much for the help!!! Kind regards, Denis Or use this // ZipDir ( fm_dirIn ; fm_fileOut ) // 10_12_23_JR WORKING // v1.0 // adds all of tree from starting directory to zip file // adapted from Solomon Duskis, http://www.jroller.com import java.io.File import java.io.FileInputStream import java.io.FileOutputStream import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream try { topDir = new File(fm_dirIn) zipOut = new ZipOutputStream ( new FileOutputStream(fm_fileOut) ); topDirLength = topDir.absolutePath.length() topDir.eachFileRecurse{ file -> relPath = file.absolutePath.substring(topDirLength).replace('\\', '/') if ( file.isDirectory() && !relPath.endsWith('/')){ relPath += "/" } entry = new ZipEntry(relPath) entry.time = file.lastModified() zipOut.putNextEntry(entry) if( file.isFile() ){ zipOut << new FileInputStream(file) } } zipOut.close() } catch (Exception e) { e.printStackTrace() } return true
January 23, 201114 yr This works awesome!!!!! Can you shed some light on how I might amend the code so I can just add a list of files to the zip instead of copying them to a directory first? My goal is to grab a bunch of files, get their locations, then create a zip and add each file to it. I guess it would be an amend, but I really thought/remember that via command line there was a way to list files to add. Any light that could be shed would be awesome. Thanks! Or use this // ZipDir ( fm_dirIn ; fm_fileOut ) // 10_12_23_JR WORKING // v1.0 // adds all of tree from starting directory to zip file // adapted from Solomon Duskis, http://www.jroller.com import java.io.File import java.io.FileInputStream import java.io.FileOutputStream import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream try { topDir = new File(fm_dirIn) zipOut = new ZipOutputStream ( new FileOutputStream(fm_fileOut) ); topDirLength = topDir.absolutePath.length() topDir.eachFileRecurse{ file -> relPath = file.absolutePath.substring(topDirLength).replace('\\', '/') if ( file.isDirectory() && !relPath.endsWith('/')){ relPath += "/" } entry = new ZipEntry(relPath) entry.time = file.lastModified() zipOut.putNextEntry(entry) if( file.isFile() ){ zipOut << new FileInputStream(file) } } zipOut.close() } catch (Exception e) { e.printStackTrace() } return true
January 23, 201114 yr The zip works. But it always returns 1, even if it doesn't. Could it be rewriten slightly to show an error in either input or output path? Also, small likely unavoidable glitch with Mac ".text clipping" files (with or without extension). The content is lost, even if plain text. I say unavoidable because native Mac command line 'zip' does this also; 'ditto' keeps that resource fork, maybe others.
November 10, 201114 yr Hello, I need to create a zip of a folder ; I was glad to find that SM script but if it seems to work (I find the output file with a good capacity) I can't open it under Winzip, either on a PC or a Mac ; I get an error I've translated Extraction towards C:UsersAdministrateurAppDataLocalT emp Use Road: not files Overlay: yes attention: name of not corresponding file: Factures_PDFLOCAL201110_octobreDub au_No + ½ l_Dubau_Louise.pdf error: no files found - nothing to make I tried to extract one after one the files ; the error occurs when the file contains an accentuated char : so No + ½ l ir really Noël Is it possible to correct the script ? Thanks for your help Noël
November 11, 201114 yr Noel... This is relevant - it is a function of using the base Java zip library. >> Java currently expects UTF-8 encoding. This generally means that if you create a ZIP file in Windows, filenames with non-ASCII characters will be mangled. The issue has been raised as Java bug ID 4244499, with a proposal to add a ZipFile constructor to take the character encoding (assuming the caller knows it). At the moment, a possible solution is to use the Arcmexer library, which allows you to set the file name encoding. This also has the advantage of being able to read encrypted ZIP files. My advice is generally: Don't use accents or other non-ASCII characters or spaces in filenames! You really don't need them that much. One historical problem is that filenames were never really intended to be a human-readable "title", but increasingly, that's how many "average users" are treating them. For the time being, there's no elegant solution to this problem, and the best we can really do is live with filenames with missing diacritics or occasional spelling changes to fit ASCII.
November 11, 201114 yr Fenton Sorry I seem to have missed this How about // ZipDir ( fm_dirIn ; fm_fileOut ) // 10_12_23_JR WORKING // v1.1 // adds all of tree from starting directory to zip file // adapted from Solomon Duskis, http://www.jroller.com import java.io.File import java.io.FileInputStream import java.io.FileOutputStream import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream try { topDir = new File(fm_dirIn) zipOut = new ZipOutputStream ( new FileOutputStream(fm_fileOut) ) topDirLength = topDir.absolutePath.length() topDir.eachFileRecurse{ file -> relPath = file.absolutePath.substring(topDirLength).replace('', '/') if ( file.isDirectory() && !relPath.endsWith('/')){ relPath += '/' } entry = new ZipEntry(relPath) entry.time = file.lastModified() zipOut.putNextEntry(entry) if( file.isFile() ){ zipOut << new FileInputStream(file) } } zipOut.close() } catch (Exception e) { return 'ERROR ' + e.getMessage() //e.printStackTrace() } if (!new File(fm_fileOut).exists()){return 'ERROR'} return true
November 11, 201114 yr Thanks for these answers ! I know that all these chars are sources of problems ; but for a basic user it's easier to understand what contains a file called "Dubau Noël bill.pdf" than called "X354_2011_bill.pdf" ! The solution was given in private to use a SM script which remove all diacrticals chars before zipping. You can find it at http://www.fmsource.com/index.php/topic/46544-formatage-de-caracteres-accentues-a-transformer-en-caracteres-sans-accent/page__p__222476__hl__removediacriticals__fromsearch__1#entry222476 Noël (alias Christmas )
November 12, 201114 yr There is a solution that might work using Ant. You need the ant.jar and ant-launcher.jar files IN THE CLASSPATH (java/extensions) but I have successfully zipped and unzipped files with diacriticals in the names using this method - seems to work with the French marks but not Żywia - must be an encoding issue there.. Thanks to Clement Hoffman for the steer basic code - needs lots of bits round it: def fm_dirSource = "/Users/RWU/Downloads/TEMP" def fm_fileDest = "/Users/RWU/Desktop/test.zip" if (new File(fm_dirSource).exists() && fm_fileDest){ def ant = new AntBuilder() ant.zip(basedir:fm_dirSource, destfile:fm_fileDest) //ant.zip(basedir:fm_dirSource, destfile:fm_fileDest, update:"true") return true } else return "ERROR" see the docs for more details http://ant.apache.or.../Tasks/zip.html
November 12, 201114 yr ... a more extended version of my original script : // USAGE : ZipAnt ( fm_dirSource ; fm_archOut ; fm_archUpdate ; fm_archCompLevel ; fm_archExclude ) // 2011_11_11 clem & John Renfrew // v1.0 // example: // ZipAnt ( pathToDir ; pathToZip ; true/false ; 0..9 ; *.html, *.csv, *.xlsx ) if ( new File(fm_dirSource).exists() && fm_archOut ){ def ant = new AntBuilder() fm_archUpdate = fm_archUpdate ?: true fm_archCompLevel = fm_archCompLevel ?: 9 ant.zip( basedir: fm_dirSource, destfile: fm_archOut, update: fm_archUpdate, level: fm_archCompLevel, excludes: fm_archExclude ) } else return "ERROR" ... diacriticals are apparently preserved ...
November 12, 201114 yr Clem better error reporting // ZipAnt ( fm_dirSource ; fm_archOut ; fm_archUpdate ; fm_archCompLevel ; fm_archExclude ) // 2011_11_11 clem & John Renfrew // v1.1 // example: // ZipAnt ( pathToDir ; pathToZip ; true/false ; 0..9 ; *.html, *.csv, *.xlsx ) if ( new File(fm_dirSource).exists() && fm_archOut ){ ant = new AntBuilder() fm_archUpdate = fm_archUpdate ?: true fm_archCompLevel = fm_archCompLevel ?: 9 try{ ant.zip( basedir: fm_dirSource, destfile: fm_archOut, update: fm_archUpdate, level: fm_archCompLevel, excludes: fm_archExclude ) } catch (e) { return e.getMessage() } // or replace with with success message of your choice return true } else return 'ERROR'
November 13, 201114 yr ... Thanks for your following of the question, and especially to the "newbie" Clem Noël
February 13, 20169 yr Can anybody explain me how can we register this function into filemaker with scriptmaster plugin ?? I did like this but it doesn't run: RegisterGroovy( "ZipDir( fm_dirIn ; fm_fileOut )" ; "import java.io.File¶ ¶ import java.io.FileInputStream¶ ¶ import java.io.FileOutputStream¶ ¶ import java.util.zip.ZipEntry¶ ¶ import java.util.zip.ZipOutputStream¶ ¶ try {¶ ¶ topDir = new File(fm_dirIn)¶ ¶ zipOut = new ZipOutputStream ( new FileOutputStream(fm_fileOut) );¶ ¶ topDirLength = topDir.absolutePath.length()¶ ¶ topDir.eachFileRecurse{ file ->¶ ¶ relPath = file.absolutePath.substring(topDirLength).replace('\', '/')¶ ¶ if ( file.isDirectory() && !relPath.endsWith('/')){¶ ¶ relPath += "/"¶ ¶ }¶ ¶ entry = new ZipEntry(relPath)¶ ¶ entry.time = file.lastModified()¶ ¶ zipOut.putNextEntry(entry)¶ ¶ if( file.isFile() ){¶ ¶ zipOut << new FileInputStream(file)¶ ¶ }¶ ¶ }¶ ¶ zipOut.close()¶ ¶ } catch (Exception e) {¶ ¶ e.printStackTrace()¶ ¶ }¶ ¶ return true" )
February 14, 20169 yr One way: you need to set a variable to this code then check that the variable you set is 1 and not an error then the function should appear in your list of external functions
February 14, 20169 yr I am obtaining a disaster zip with a lot of directories and nosense. If i put this code: relPath = file.absolutePath.substring(topDirLength).replace('\\', '/') There is an error in the java. And if I put with only one '\' i get a bad zip.... Can anybody helps me ? Thanks. Edited February 16, 20169 yr by jsubiros
February 8, 20196 yr Newbies Hello There, I am trying to use John's script v1.1 with ScriptMaster plugin but without success. I have a little experience with this plugin and for instance, i am able to register and evaluate the script provided by 360Works "Zip File( src ; destination )" without any issue. But my actual need is to zip a folder and i was very happy to find this post. Unfortunately, i am unable to Register John's script (evaluating into a variable it returns just "ERROR" instead of 1) and i am also unable to evaluate/perform it; i always get this message : java.lang.reflect.InvocationTargetException Are there specific requirements to register/evaluate John's script with ScriptMaster ?
February 8, 20196 yr Newbies Hi Ryan, Thank you for helping ! Yes my ScriptMaster version is 5.1. Sounds like there are no update since june 2018. Edited February 8, 20196 yr by FileMakerNewbee
February 8, 20196 yr I have seen the InvocationTargetException happen at different points. Please send an email to [email protected] with your plugin logs. This will create an official support ticket for you. See this page for log locations. Make sure to reproduce the error and then send the logs before any restarts of FileMaker as restarting will overwrite the logs.
February 9, 20196 yr Let me look at whether I have amended that code at all too... it IS now over 8 years old!!
February 11, 20196 yr Newbies John, it is very kind from you. I understand the thread is very old. What i can tell is that i have not found many other solution like yours.
February 15, 20196 yr Newbies Hello there ! For potential futur visitor, i have to say i found out a free and simple way by using BaseElement "Zip" and "FileListFolder" functions : https://baseelementsplugin.zendesk.com/hc/en-us/articles/206609058-BE-Zip https://baseelementsplugin.zendesk.com/hc/en-us/articles/204700868-BE-FileListFolder It works like a charm and appear to be more straight forward than using a groovy and ScriptMaster. Just had the surprise on windows that a path had to begin with C:/… instead of usual /C:/… whereas on macOS, the path can start as usual by /Volumes/Hard Disk/… Here is an FileMaker script sample that worked for me : Set Variable [ $path; Value:Substitute ( <FileMakerPathOfAFolder> ;"file:/" ; If ( Get ( SystemPlatform ) = 1 ; "/Volumes/" ; "" ))] Set Variable [ $files_names; Value:BE_FileListFolder ( $path ) ] Loop Set Variable [ $i; Value: $i + 1 ] Set Variable [ $files_path; Value:List( $files_path ; $path & GetValue ( $files_names ; $i ) ) ] End of Loop if [ $i = CountValues ( $files_names ) ] End of Loop Set Variable [ $Zip; Value:BE_Zip ( $files_path ) ] . Edited February 15, 20196 yr by FileMakerNewbee
Create an account or sign in to comment