zipping a file by command line

I use this code to zip a file:

dim dlg as new OpenDialog dlg.InitialDirectory = SpecialFolder.Desktop dim f as FolderItem = dlg.ShowModalWithin(self) if f <> nil then dim h as FolderItem = SpecialFolder.Desktop.Child("myZip") // if h = nil and not h.Exists then //h.CreateAsFolder //end if dim s as new Shell s.Execute "zip " + h.ShellPath + " " + f.ShellPath end if

The file gets zipped all right, but when I unzip it by double-click I find it nested in two folders:

  1. Users, containing the following folder
  2. CarloRubini, containing the actual file

Is there a way to zip the file in such a way that the two folders get skipped?

Thank you.

My guess from that is that you need to cd into the folder above “f” before creating the zip file. When yo upass h.ShellPath, you’re passing the complete path, so:


Therefore, you need to cd into /Users/CarloRubini/ and then execute the ZIP command:

s.Execute "cd " + f.Parent.NativePath + " ; zip " + h.ShellPath + " " + f.Name

I have a similar problem. In my program I create a temporary folder with all files/folders generated by my program. Let’s say the folder is stored in SpecialFolder.Desktop.

I want to let my users know where the zip file is created. I would like to offer him an OpenDialog where he can select the file path and its name. Now, unnoticed by the user, a zip file should be output from the temporary folder exactly at this point. After this has happened successfully (you can check this via the shell object), the temporary folder should be deleted on the desktop.

The above shell call to create zip files should also work on Linux, right? Is there a Windows counterpart?

Previously, Apple’s website gave a detailed description of the ZIP command, this page has not existed for a long time and one can only hope that the shell command is not deprecated!

Any suggestions or hints?

Hi Tim,
it works all right. Yet only if the name of the file selected to be zipped does not contain any space.
I unsuccesfuly tried encodeUrlComponent.
Any idea?

Thank you.

Put the name inside quotes (the one you pass to the shell)… just like in the Terminal).

Edit (explanation):
You have a “Windows 10” folder in your user directory.

Fire the Terminal,
type: ls Windows 10 -l

you get an error.

type: ls "Windows 10" -l
you get the list of ityems in the passed folder name.

Use, in the Terminal, man zip and read…

I’ve created a small sample project. It creates the temporary folder which should be zipped on a user selected place. But it did not create a zip file.

Zip file using macOS Terminal - Xojo Project

@Martin Trippensee: what do you expect after an error? “Zip warning: name not matched Ohne Titel, zip error: nothing to do!”

Here is a shell that, at present, works, ignoring the parent folders. It seems that -j does the trick:
s.Execute "zip -j " etc.

As for the output name, I noticed that I have to leave out the extension part of the fileName; or add .zip to f.displayName

dim dlg as new OpenDialog dlg.InitialDirectory = SpecialFolder.Desktop dim f as FolderItem = dlg.ShowModalWithin(self) if f <> nil then dim r() as String = f.DisplayNameSplit(".") dim h as FolderItem = SpecialFolder.Desktop.Child(r(0))//or f.displayName + ".zip" dim s as new Shell s.Execute "zip -j " + h.ShellPath + " " + f.ShellPath end if

Thanks again.

Today (AFAIK) DisplayName and Name behave the same, but this may change. You better use Name instead.

I will try that once back home.

The man zip page states for file extension:

Edit (remove useless spaces):

If the name of the zip archive does not contain an extension, the extension .zip is added. If the name already contains an extension other than .zip, the existing extension is kept unchanged. How- ever, split archives (archives split over multiple files) require the .zip extension on the last split.

I did a step forward.

[code]Dim input As FolderItem = TempFolder
Dim output As FolderItem = SpecialFolder.Picture.Child(““)
Dim s As String

s = “cd “ + input.ShellPath + “;“ +_
“zip -r “ + output.ShellPath + “ “ + input.ShellPath + “ *“
This now packs my temporary folder including all files/folders into a user selected file path. But it stores a third folder in it „Users/…“. Please test it. I don’t want the third folder. Can someone help please?

@Emile Schwarz
I read the zip page, but in practice I had to resort to the above code.

@Martin Trippensee

May be the -j parameter may help you as it helped me (see above).

Sadly not. Adding -j after -r won’t create anything and i‘ll also not get any Shell.Result message.

Surround the names with double quotes. Using Martin’s code above:

s = "cd """ + input.ShellPath + """ ; " +_ "zip -r """ + output.ShellPath + """ """ + input.ShellPath + """ *" Shell1.Execute(s)

Also, it’s good etiquette for the forums if you disable “Use smart quotes and dashes” in the Mac’s “Preferences” -> “Keyboard” -> “Text” settings :smiley:

@Tim Jones that’s totally weird. Using your String do also include the „Users/…“ folders on my Mac. I modified the string to

s = "cd """ + input.ShellPath + """ ; " +_ "zip -r """ + output.ShellPath + """" + " " + """ + input.ShellPath + "" *"
Now it only writes to files I wanted, but if the output filename contains whitespaces, i‘ll get for example „Ohne\“ instead of „Ohne“. Why?

Because inside of quotes you don’t need to do the shell encoding I would guess.

How should I handle this clue? You suggest using NativePath instead?


Apologies - I realize that I didn’t change that in my code examples. Trixie is correct.

You should always use “.NativePath” and quotes for the best results on all three platforms when dealing with passing file paths in a shell.