Jump to content
View in the app

A better way to browse. Learn more.

FMForums.com

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

How To Zip A Directory?

Featured Replies

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

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].

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

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



  • 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

  • 4 weeks later...

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

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.

  • 9 months later...

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

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.

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

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 :yep: )

Merci Noel...

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

... 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 ...

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'

... Thanks for your following of the question, and especially to the "newbie" Clem ;)

Noël

  • 3 years later...
  • Newbies

Thank you for this helpful function, Jhon.

Raphaël.

  • 1 year later...

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"
 

 )

 

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

 

 

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 by jsubiros

  • 2 years later...
  • 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 ?

  • Newbies

Hi Ryan,

Thank you for helping !

Yes my ScriptMaster version is 5.1.

Sounds like there are no update since june 2018.

Edited by FileMakerNewbee

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. 

Let me look at whether I have amended that code at all too... it IS now over 8 years old!!

  • 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.

  • 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 by FileMakerNewbee

Create an account or sign in to comment

Important Information

By using this site, you agree to our Terms of Use.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.