spaces in filename passed as variable to "do shell script"

I’m very new to applescript and have been pulling together an applescript app that will install and configure printers for my helpdesk technicians. I’m having some trouble getting file names with spaces to work correctly in two regions of my script. the file names are passed to the scripts using variables so that I can keep the script cleaner and more universal for the multiple printers I need to setup.

Here’s the apple script app:


-- This applescript application will copy the bundled printer PPD driver files and install a specified printer with all the appropriate options for use.
-- Script Created by MD
-- Script Updated on July 3, 2014



-- This will prompt user to confirm the installation of the printer and performs the printer installation.
set question to display dialog "This application will install and configure a new Xerox Printer on this computer.  Please click Install if you would like to continue." buttons {"Cancel", "Install"} default button 2

set answer to button returned of question

-- If user cancels the installation then application quits
if answer is equal to "Cancel" then
	quit
	
	-- If user chooses Install then application prompts user to choose printer to install
else if answer is equal to "Install" then
	--Ask user to choose printer from list and confirm
	(choose from list {"CPX1", "CPX2", "CPX3"} ¬
		with prompt "Please choose the name of the printer you'd like to install and click OK.  Please note that after you click OK you will be prompted to enter your password in order for this printer installation to contine.")
	set theprinterdisplayname to result as text
	
	-- sets the PrinterModel, and printerlocation based on theprinterdisplayname variable
	if theprinterdisplayname is equal to "CPX1" then
		set PrinterModel to "5855"
		set PrinterLocation to "Department_Hallway"
	else if theprinterdisplayname is equal to "CPX2" then
		set PrinterModel to "5855"
		set PrinterLocation to "VP_Office"
	else if theprinterdisplayname is equal to "CPX3" then
		set PrinterModel to "7855"
		set PrinterLocation to "Back_Hallway"
	else if theprinterdisplayname is equal to "CPX4" then
		set PrinterModel to "5855"
		set PrinterLocation to "Facility_Office"
		
	end if
	
	-- sets the PPD file, resource location path, printer model specific printer options, based on PrinterModel variable
	if PrinterModel is equal to "5855" then
		set PPDFile to "Xerox WorkCentre 5855.gz"
		set resourcePath to POSIX path of (path to resource "" & PPDFile & "")
		set ModelOptions to "-o PageSize=Letter -o XRTrays=FiveTraysHCTT -o XRHolePunch=TruePunch -o XRLanFax=False -o XRJobStorage=True -o XRFinisher=OF -o XRAccountingSystem=XSA -o XRAccountingPrompt=Prompt -o XRAccountingMaskUserID=False"
	else if PrinterModel is equal to "7845" then
		set PPDFile to "Xerox WorkCentre 7845.gz"
		set resourcePath to POSIX path of (path to resource "" & PPDFile & "")
		set ModelOptions to "-o PageSize=Letter -o XRTrays=FiveTraysHCTT -o XRHolePunch=23Unit -o XRLanFax=False -o XRJobStorage=True -o XRFinisher=AFinisher -o XRAccountingSystem=XSA -o XRAccountingPrompt=Prompt -o XRAccountingMaskUserID=False"
	else if PrinterModel is equal to "7855" then
		set PPDFile to "Xerox WorkCentre 7855.gz"
		set resourcePath to POSIX path of (path to resource "" & PPDFile & "")
		set ModelOptions to "-o PageSize=Letter -o XRTrays=FiveTraysHCTT -o XRHolePunch=23Unit -o XRLanFax=False -o XRJobStorage=True -o XRFinisher=ProfessionalFinisher -o XRAccountingSystem=XSA -o XRAccountingPrompt=Prompt -o XRAccountingMaskUserID=False"
	else if PrinterModel is equal to "7775" then
		set PPDFile to "Xerox WorkCentre 7775.gz"
		set resourcePath to POSIX path of (path to resource "" & PPDFile & "")
		set ModelOptions to "-o PageSize=Letter -o XRTrays=FiveTraysHCTT -o XRHolePunch=TruePunch -o XRLanFax=False -o XRJobStorage=True -o XRFinisher=ProfessionalFinisher -o XRAccountingSystem=XSA -o XRAccountingPrompt=Prompt -o XRAccountingMaskUserID=False"
		
	end if
	
	-- Sets POSIX path of the PPD file  that will be used with the printer on target system.	
	set PPDTargetPath to POSIX path of ("/Library/Printers/PPDs/Contents/Resources/") & "" & PPDFile & ""
	
	-- Sets path to location where PPD files are stored on target system
	set PPDPath to "/Library/Printers/PPDs/Contents/Resources/"
	
	-- This is the shell script that will be run to install and configure the the printer.  It will be called later.
	set installscript to "/usr/sbin/lpadmin -p '" & theprinterdisplayname & "' -v 'lpd://" & theprinterdisplayname & ".domain.com/lp' -D '" & theprinterdisplayname & "' -L '" & PrinterLocation & "' -P '" & PPDTargetPath & "' -E " & ModelOptions & ""
	
	-- Test to see if Driver file is already installed then depending on result copy driver file and install printer or just install printer.
	tell application "Finder"
		if exists PPDTargetPath as POSIX file then
			set PPDExists to true
			
		else
			set PPDExists to false
		end if
	end tell
	
	if PPDExists is equal to false then
		do shell script "cp -R -n -p " & resourcePath & " " & PPDPath & "" with administrator privileges
		
		-- Pause to wait for file to copy
		delay 3
		
		do shell script installscript
		
		quit
		
	else if PPDExists is equal to true then
		do shell script installscript
		
		quit
		
	end if
	
end if


When I run the above applescript app i get an error the when the CP command is run to copy the driver file. The error reads: "cp: /users/user/documents/scripts/completed/testscript.app/Contents/Resources/Xerox: No such File or directory cp: WorkCentre: No such file or directory cp: 5855.gz: No such file or directory

The spaces in the file name are not being interpreted correctly when the script executes and creates the resourcePath variable below:

if PrinterModel is equal to "5855" then
		set PPDFile to "Xerox WorkCentre 5855.gz"
		set resourcePath to POSIX path of (path to resource "" & PPDFile & "")
		set ModelOptions to "-o PageSize=Letter -o XRTrays=FiveTraysHCTT -o XRHolePunch=TruePunch -o 

and then passes it to the cp command.

do shell script "cp -R -n -p " & resourcePath & " " & PPDPath & "" with administrator privileges

I’m not sure if this is a well written code or not but it does all work exactly as intended if the PPDfile variable has no spaces in the filename. I however need it to work with spaces in the filename.

I’ve tried various combinations of escaping the spaces with a \ or a \ but all of them seem to cause problems in one spot or another.

Can anyone see the error of my ways??

Thanks in advance for the help. :slight_smile:
Matt

Hi,

first of all forget all “quotations” including the leading and trailing empty strings while composing the path, for example instead of

set PPDTargetPath to POSIX path of ("/Library/Printers/PPDs/Contents/Resources/") & "" & PPDFile & ""

then just write

set PPDTargetPath to "/Library/Printers/PPDs/Contents/Resources/" & PPDFile 

paths separated by slashes are POSIX paths anyway

then use ever ever ever quoted form of when passing any path or other parameters which can contain space characters to the shell. AppleScript does the right thing


do shell script "cp -R -n -p " & quoted form of resourcePath & space & quoted form of PPDPath with administrator privileges

or


set installscript to "/usr/sbin/lpadmin -p " & quoted form of theprinterdisplayname & " -v " & quoted form of ("lpd://" & theprinterdisplayname & ".domain.com/lp") & " -D " & quoted form of theprinterdisplayname & " -L " & quoted form of PrinterLocation & " -P " & quoted form of PPDTargetPath & " -E " & ModelOptions

the model options are alway -o switches with a following non-spaced parameter so don’t use quoted form of there

PS: this is a slightly optimized version of the script.
The printers are declared in the first property line as a list of records.
The choose from list part uses an index prefix to easily get the proper printer record
The common printer options are declared in another property and the specific options are appended later in the script


property printers : {{model:"5855", location:"Department_Hallway"}, ¬
	{model:"5855", location:"VP_Office"}, ¬
	{model:"7855", location:"Back_Hallway"}, ¬
	{model:"5855", location:"Facility_Office"}}

property commonPrinterOptions : "-o PageSize=Letter -o XRTrays=FiveTraysHCTT -o XRLanFax=False -o XRJobStorage=True -o XRAccountingSystem=XSA -o XRAccountingPrompt=Prompt -o XRAccountingMaskUserID=False" & space

try
	-- This will prompt user to confirm the installation of the printer and performs the printer installation.
	set question to display dialog "This application will install and configure a new Xerox Printer on this computer. Please click Install if you would like to continue." buttons {"Cancel", "Install"} default button 2
on error number n
	if n = -128 then quit
end try

-- If user chooses Install then application prompts user to choose printer to install
--Ask user to choose printer from list and confirm
set chosenPrinter to (choose from list {"1 CPX1", "2 CPX2", "3 CPX3", "4 CPX4"} ¬
	with prompt "Please choose the name of the printer you'd like to install and click OK. Please note that after you click OK you will be prompted to enter your password in order for this printer installation to continue.")
if chosenPrinter is false then quit

-- get the first character as index and get the printer record from the printers list
set chosenPrinter to first character of item 1 of chosenPrinter as integer
set currentPrinter to item chosenPrinter of printers
set PrinterModel to currentPrinter's model
set PrinterLocation to currentPrinter's location

if PrinterModel is "5855" then
	set ModelOptions to commonPrinterOptions & "-o XRHolePunch=TruePunch -o XRFinisher=OF"
else if PrinterModel is "7845" then
	set ModelOptions to commonPrinterOptions & "-o XRHolePunch=23Unit -o XRFinisher=AFinisher"
else if PrinterModel is "7855" then
	set ModelOptions to commonPrinterOptions & "-o XRHolePunch=23Unit -o XRFinisher=ProfessionalFinisher"
else if PrinterModel is "7775" then
	set ModelOptions to commonPrinterOptions & "-o XRHolePunch=TruePunch -o XRFinisher=ProfessionalFinisher"
end if
set PPDFile to "Xerox WorkCentre " & PrinterModel & ".gz"
set resourcePath to POSIX path of (path to resource PPDFile)

-- Sets POSIX path of the PPD file that will be used with the printer on target system.  
set printerDescriptionFolder to POSIX path of (path to printer descriptions from local domain)

-- Sets path to location where PPD files are stored on target system
set PPDResourcesFolder to printerDescriptionFolder & "Contents/Resources/"
set PPDTargetPath to PPDResourcesFolder & PPDFile

-- This is the shell script that will be run to install and configure the the printer. It will be called later.
set installscript to "/usr/sbin/lpadmin -p " & quoted form of theprinterdisplayname & " -v " & quoted form of ("lpd://" & theprinterdisplayname & ".domain.com/lp") & " -D " & quoted form of theprinterdisplayname & " -L " & quoted form of PrinterLocation & " -P " & quoted form of PPDTargetPath & " -E " & ModelOptions
-- Test to see if Driver file is already installed then depending on result copy driver file and install printer or just install printer.
tell application "Finder" to set driverExists to exists PPDTargetPath as POSIX file

if not driverExists then
	do shell script "cp -R -n -p " & quoted form of resourcePath & space & quoted form of PPDResourcesFolder with administrator privileges
	
	-- delay is not necessary, cp waits
	-- delay 3
end if
do shell script installscript
quit

Wow… Thank-you Stefan! Great information! :smiley:

This optimized version looks great and I’m learning more from seeing how you’ve accomplished this. I had to add a line of code in to set theprinterdisplayname as it was not declared in your version. I’ve also found that for some reason the additional modeloptions aren’t being processed correctly. the common options are processing correctly and if I temporarily add the additional options for one printer into the commonPrinterOptions they process correctly. Perhaps something about how they are combined is not working correctly?

Here’s what have right now:

property printers : {{name:"CPX1", model:"5855", location:"Department_Hallway"}, ¬
   {name:"CPX2", model:"5855", location:"VP_Office"}, ¬
   {name:"CPX3", model:"7855", location:"Back_Hallway"}, ¬
   {name:"CPX4", model:"5855", location:"Facility_Office"}}

property commonPrinterOptions : "-o PageSize=Letter -o XRTrays=FiveTraysHCTT -o XRLanFax=False -o XRJobStorage=True -o XRAccountingSystem=XSA -o XRAccountingPrompt=Prompt -o XRAccountingMaskUserID=False" & space

try
   -- This will prompt user to confirm the installation of the printer and performs the printer installation.
   set question to display dialog "This application will install and configure a new Xerox Printer on this computer. Please click Install if you would like to continue." buttons {"Cancel", "Install"} default button 2
on error number n
   if n = -128 then quit
end try

-- If user chooses Install then application prompts user to choose printer to install
--Ask user to choose printer from list and confirm
set chosenPrinter to (choose from list {"1 CPX1", "2 CPX2", "3 CPX3", "4 CPX4"} ¬
   with prompt "Please choose the name of the printer you'd like to install and click OK. Please note that after you click OK you will be prompted to enter your password in order for this printer installation to continue.")
if chosenPrinter is false then quit

-- get the first character as index and get the printer record from the printers list
set chosenPrinter to first character of item 1 of chosenPrinter as integer
set currentPrinter to item chosenPrinter of printers
set theprinterdisplayname to currentPrinter's name
set PrinterModel to currentPrinter's model
set PrinterLocation to currentPrinter's location

if PrinterModel is "5855" then
   set ModelOptions to commonPrinterOptions & "-o XRHolePunch=TruePunch -o XRFinisher=OF"
else if PrinterModel is "7845" then
   set ModelOptions to commonPrinterOptions & "-o XRHolePunch=23Unit -o XRFinisher=AFinisher"
else if PrinterModel is "7855" then
   set ModelOptions to commonPrinterOptions & "-o XRHolePunch=23Unit -o XRFinisher=ProfessionalFinisher"
else if PrinterModel is "7775" then
   set ModelOptions to commonPrinterOptions & "-o XRHolePunch=TruePunch -o XRFinisher=ProfessionalFinisher"
end if
set PPDFile to "Xerox WorkCentre " & PrinterModel & ".gz"
set resourcePath to POSIX path of (path to resource PPDFile)

-- Sets POSIX path of the PPD file that will be used with the printer on target system. 
set printerDescriptionFolder to POSIX path of (path to printer descriptions from local domain)

-- Sets path to location where PPD files are stored on target system
set PPDResourcesFolder to printerDescriptionFolder & "Contents/Resources/"
set PPDTargetPath to PPDResourcesFolder & PPDFile

-- This is the shell script that will be run to install and configure the the printer. It will be called later.
set installscript to "/usr/sbin/lpadmin -p " & quoted form of theprinterdisplayname & " -v " & quoted form of ("lpd://" & theprinterdisplayname & ".domain.com/lp") & " -D " & quoted form of theprinterdisplayname & " -L " & quoted form of PrinterLocation & " -P " & quoted form of PPDTargetPath & " -E " & ModelOptions
-- Test to see if Driver file is already installed then depending on result copy driver file and install printer or just install printer.
tell application "Finder" to set driverExists to exists PPDTargetPath as POSIX file

if not driverExists then
   do shell script "cp -R -n -p " & quoted form of resourcePath & space & quoted form of PPDResourcesFolder with administrator privileges
   
end if
do shell script installscript
quit

actually the syntax is correct. Maybe the -o parameters must passed in a specific order.

Hmm. Ok. I’ll do some more testing. I was wondering if that might be the case.

Thank-you,
Matt

Stefan - Just wanted to post back and let you know that I resolved the problem I was having. In one case the -o parameter needed to be passed in a specific order and in the other case one of the -o parameters was incorrect and was causing the printer config to exit prematurely leaving the printer without any options selected.

Everything is working great now. Thanks again for your help on this!

Matt