Unzipping multiple files using Shell Script

Good Evening,

I have a script that successfully unzips individual zip files I have downloaded by using a shell script.

What I would like to do is select multiple files in the dialog box and unzip them all to the same folder. I realise that when multiple selections are made they are added to an array. Is there an easy way to loop through each selected file in the user_Choice array and unzip them to the Terminal Charts folder?

on run
	
	display dialog "This programme unzips files" with title "MAKE DOCUMENT PACK" buttons {"Choose Files", "Exit Script"} default button "Choose Files" cancel button "Exit Script" giving up after 20
	choose file with prompt "Please select the downloded .zip files" with multiple selections allowed
	open {result}
	
end run

on open user_Choice
	
	set c to POSIX path of (path to downloads folder) --setting the path to the downloads folders.
	
	set DestinationDirectory to c & "Terminal Charts"
	
	do shell script "/usr/bin/ditto -xk " & POSIX path of user_Choice & space & quoted form of DestinationDirectory --Unzip the Terminal Chart.zip file
	
end open


In your run handler, it would be good to edit the last instruction.

open result

No need to enclose result between brackets because display dialog … with multiple selections allowed returns always a list.

on run
	
	display dialog "This programme unzips files" with title "MAKE DOCUMENT PACK" buttons {"Choose Files", "Exit Script"} default button "Choose Files" cancel button "Exit Script" giving up after 20
	choose file with prompt "Please select the downloded .zip files" with multiple selections allowed
	open result # EDITED
	
end run

on open user_Choice
	
	set c to POSIX path of (path to downloads folder) --setting the path to the downloads folders.
	
	set DestinationDirectory to quoted form of (c & "Terminal Charts")
	repeat with aPath in user_Choice
		do shell script "/usr/bin/ditto -xk " & quoted form of (POSIX path of aPath) & space & DestinationDirectory --Unzip the Terminal Chart.zip file
	end repeat
end open


Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) lundi 29 juillet 2019 12:44:32

The ditto command accepts multiple source files with the -x option. So, an alternative approach to using a loop with multiple calls to ditto is to create a list of source files with POSIX paths. Revising Yvan’s script to take this approach is:

on run
	
	display dialog "This programme unzips files" with title "MAKE DOCUMENT PACK" buttons {"Choose Files", "Exit Script"} default button "Choose Files" cancel button "Exit Script" giving up after 20
	choose file with prompt "Please select the downloded .zip files" with multiple selections allowed
	open result # EDITED
	
end run

on open user_Choice
	
	set c to POSIX path of (path to downloads folder) --setting the path to the downloads folders.
	
	set DestinationDirectory to quoted form of (c & "Terminal Charts")
	
	set userPosixFiles to {}
	repeat with aFile in user_Choice
		set end of userPosixFiles to (quoted form of POSIX path of aFile) & " "
	end repeat
	
	do shell script "/usr/bin/ditto -xk " & userPosixFiles & DestinationDirectory
	
end open

I’ve run some timing tests with AppleScripts using command-lines utilities (although not with ditto) and this approach is generally faster. However, it’s certainly less flexible and looping through the individual source files may be preferable for this reason.

all zip formats supported by ditto ?

display dialog "This program unzips files" with title ¬
	"MAKE DOCUMENT PACK" buttons {"Choose Files", "Exit Script"} ¬
	default button "Choose Files" cancel button "Exit Script" giving up after 20

choose file of type {"public.archive"} ¬
	with prompt "Please select the downloaded .zip files" with multiple selections allowed
set user_Choice to result

set c to POSIX path of (path to downloads folder)
set DestinationDirectory to quoted form of (c & "Terminal Charts")

repeat with aPath in user_Choice
	set aPath to quoted form of (POSIX path of aPath)
	do shell script "/usr/bin/ditto -xk " & aPath & space & DestinationDirectory
	if result = 1 then display dialog ¬
		"ditto can't unzip archive " & return & return & aPath buttons {"OK"}
end repeat

KniazidisR. I don’t think this will work properly:

   do shell script "/usr/bin/ditto -xk " & aPath & space & DestinationDirectory
   if result = 1 then display dialog ¬
       "ditto can't unzip archive " & return & return & aPath buttons {"OK"}

Instead don’t you have to do something like:

try
	do shell script "/usr/bin/ditto -xk " & aPath & space & destinationDirectory
on error
	display dialog "ditto can't unzip archive " & return & return & aPath buttons {"OK"}
end try

I’m not sure, but in my opinion, the do shell script command returns the status number instead of the error number. Are you sure that the try block understands that the result = 1 means an error? I do not have WinZip archive to check

If the termination status is other than 0, do shell script throws an error. From Tech Note 2065:

So AppleScript is smarter than I thought. Thanks for the info, Shane.

KniazidisR. I ran your version of Yvan’s script on a faulty zip file and the script returned a dialog with the following:

“ditto Couldn’t read PIZip signature (1)”

The dialog buttons were “Edit” and “OK”. I clicked on OK and the script terminated. I repeated this but clicked on Edit, and Script Editor activated and opened your script.

I then modified your script utilizing a try statement. The dialog noted above did not appear, and, instead, the dialog contained in the script was shown.

To supplement the quote posted by Shane, the man page for the ditto command contains the following:

“ditto returns 0 if everything is copied, otherwise non-zero.”

So I was right that ditto may not work with some formats. Although it was only my assumptions. Thank you for checking and for providing information. And yes, you are right, need to use the try block form. As I can see now, it solves 2 problems at once: 1) replaces the default behavior of reacting to an error 2) allows the process to continue.

So, with your help and with God’s help, the improved script should be something like this:


display dialog "This program unzips files" with title ¬
	"MAKE DOCUMENT PACK" buttons {"Choose Files", "Exit Script"} ¬
	default button "Choose Files" cancel button "Exit Script" giving up after 20

choose file of type {"public.archive"} ¬
	with prompt "Please select the downloaded .zip files" with multiple selections allowed
set user_Choice to result

set DestinationDirectory to quoted form of (POSIX path of (path to downloads folder) & "Terminal Charts")

repeat with aPath in user_Choice
	set aPath to quoted form of (POSIX path of aPath)
	try
		do shell script "/usr/bin/ditto -xk " & aPath & space & DestinationDirectory
	on error
		display dialog "ditto can't unzip archive " & return & return & aPath buttons {"OK"}
	end try
end repeat

Thank you all for this topic and idea. The script is one of the most practical, and I saved it in my library of the best scripts.

KniazidisR. I tested your revised script and it works well

I noticed that your script does not include the open handler, which was a part of the OP’s script. The OP mentions selecting the zip files from a dialog, so perhaps this is not important.

I have an on run handler. It’s just implicit. Also, I removed the creation of unnecessary intermediate variables. 1) do not need extra lines of code, 2) do not need to waste memory.

The open handler is not needed here at all, since this is not a droplet. And my script prevents the choosing from user no archive files too.

KniazidisR. It wasn’t clear to me if the OP wanted to be able to drag and drop zip files for processing. If not, then I agree that the open handler should not be included.

When I first tried Yvan’s version of the script, I saved it as an Applescript application and then command-dragged the script to the Finder toolbar to create an icon. I could then click on this icon to select zip files from a dialog or I could drag and drop zip files from the Finder to the icon for processing. I don’t know if this is what the OP intended, but it worked well.

I should have explained all of this better–sorry.

I do not like droplets. I prefer the code that restricts the user’s choice initially. And in terms of saving computer resources, it is better to have a running none stay-open simple applet. Droplets, however, I like when they are executed not on my computer (that is, on the sites). :wink:

peavine wrote :

The original script posted by KevzScripts contained the two handlers so I assumed that it was what was wanted !

I often write scripts with these two ways of use.
I really don’t understand what is wrong with droplets except perhaps the fact that I will not use this structure for a script able to delete files.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mardi 30 juillet 2019 18:11:38

Okay, it’s my fault. I could not change the structure of the script. I do not like droplets, but of course it’s wrong to impose my preferences.

Yvan. That was my assumption as well, although KniazidisR could be correct that the OP just found the script online. Whichever the case, the OP has what he wants.

I had never seen a script written with this dual-functionality (two ways of use), and it will improve a number of my existing scripts. It’s always nice to learn something new. :slight_smile:

There was another. I got it wrong there. In less than a minute, I realized that I had made a mistake and erased the message. Also, AppleScript is my new hobby, not a profession. I am a dinosaur from Macro Assembler times. So, sometimes, I can not remember something from AppleScript. I am sorry.

Droplet variant:


display dialog "This program unzips files" with title ¬
	"MAKE DOCUMENT PACK" buttons {"Choose Files", "Exit Script"} ¬
	default button "Choose Files" cancel button "Exit Script" giving up after 20

choose file of type {"public.archive"} ¬
	with prompt "Please select the downloaded .zip files" with multiple selections allowed
open result

on open user_Choice
	
	set DestinationDirectory to quoted form of (POSIX path of (path to downloads folder) & "Terminal Charts")
	
	repeat with aPath in user_Choice
		set aPath to quoted form of (POSIX path of aPath)
		try
			do shell script "/usr/bin/ditto -xk " & aPath & space & DestinationDirectory
		on error
			display dialog "ditto can't unzip archive " & return & return & aPath buttons {"OK"}
		end try
	end repeat
	
end open

:slight_smile:

Wow, I love MacScripter.

This is exactly what I needed. Thank you to everyone who included improvements to my script. I indeed had it setup to allow files to be dragged and dropped.

Again, thank you

The question asked by the OP has been answered but I thought I might add a quick footnote.

A standard install of macOS includes the unzip command-line utility, which has a number of options not available in ditto. By way of example, ditto overwrites existing files in the destination folder, while unzip has various options in this regard.

The only change needed in Yvan’s script to use unzip is:

do shell script "/usr/bin/unzip " & quoted form of (POSIX path of aPath) & " -d " & DestinationDirectory