Posted on 12-09-2017 10:37 AM
I'm trying to create a script that will output a png file from an icns file using sips command.
The script uses read to capture path to icns file, and to capture name of the png file it outputs.
The script outputs the png file to /private/tmp/
directory...or it should:
#!/bin/sh
# Prompt for source file
/usr/bin/read -p "Drag ICNS source file into Terminal and hit RETURN: " SOURCEFILE
# Prompt for output file name
/usr/bin/read -p "Provide output file name (no spaces!) an hit RETURN: " OUTPUTFILE
# Create file
/usr/bin/sips --setProperty format png --resampleHeightWidthMax 128 "$SOURCEFILE" --out /private/tmp/"$OUTPUTFILE"
exit 0
The script is executable (755). I navigate to the folder and run the script (using obligatory "./" since I'm in the directory the script is in). I'm using BBEdit 12 for test. Here is what I get:
$ ./createIconJSS120png.sh
Drag ICNS source file into Terminal and hit RETURN: /Applications/BBEdit.app/Contents/Resources/BBEditApplication.icns
Provide output file name (no spaces!) an hit RETURN: BareBones_BBEdit12.png
Warning: not a valid file - skipping
Error 4: no file was specified
Try 'sips --help' for help using this tool
I tried using using quotes, in case there is ever a space in the icns path:
"$SOURCEFILE"
I also tried using:
"${SOURCEFILE}"
Running the command manually works fine, so pretty sure it is an issue with the read input:
$ /usr/bin/sips --setProperty format png --resampleHeightWidthMax 128 /Applications/BBEdit.app/Contents/Resources/BBEditApplication.icns --out /private/tmp/BareBones_BBEdit12.png
/Applications/BBEdit.app/Contents/Resources/BBEditApplication.icns
/private/tmp/BareBones_BBEdit12.png
Any ideas why the read command is not capturing input and passing to the script?
Solved! Go to Solution.
Posted on 12-10-2017 07:13 PM
Revisited with a fresh set of eyes, for some reason the read
command chokes when you use it's entire path /usr/bin/read
.
This works:
#!/bin/sh
# Prompt for source file
echo "Drag *.icns file into Terminal window and hit RETURN"
read INPUTFILE
# Prompt for output name
echo "Provide Vendor_Application.png name and hit RETURN"
read OUTPUTFILE
# Create file
/usr/bin/sips --setProperty format png --resampleHeightWidthMax 128 "$INPUTFILE" --out ~/Desktop/"$OUTPUTFILE"
# Open Desktop folder
/usr/bin/open ~/Desktop
exit 0
The same script with the full /usr/bin/read
path fails...no idea why.
¯_(ツ)_/¯
Posted on 12-09-2017 03:21 PM
I would suggest rewriting it into functions and breaking the read onto it's own line. I've never done reads on the same line as the echo directing the user on what to do so I suspect that might be the problem, though I'm not certain on that.
Putting them into discrete functions allows you to catch errors more easily, like someone accidentally hitting return without dragging in a file or providing a name, and running the function again.
Here's a rewrite:
#!/bin/bash
function readOutput ()
{
echo "Provide output file name (no spaces!) and hit RETURN: "
read OUTPUTFILE
if [ ! -z "$OUTPUTFILE" ]; then
## Get just the base name of the outputfile. We will add an extension ourselves in the next step
OUTPUTFILE="${OUTPUTFILE%.*}"
## Create file with .png extension
/usr/bin/sips --setProperty format png --resampleHeightWidthMax 128 "$SOURCEFILE" --out /private/tmp/"${OUTPUTFILE}.png"
exit 0
else
## If nothing was entered before hitting RETURN, loop back and run the function again
readOutput
fi
}
function readSource ()
{
echo "Drag ICNS source file into Terminal and hit RETURN: "
read SOURCEFILE
if [ ! -z "$SOURCEFILE" ]; then
## If we got something, move onto the readOutput function to get a name for the file
readOutput
else
## If nothing was entered before hitting RETURN, loop back and run the function again
readSource
fi
}
## Run the readSource function to get things started
readSource
The above was tested and works, at least for me, so hopefully for you too!
And BTW, I'm not sure what the end goal is, but it sounds like you're trying to write a script to convert ICNS icons into PNGs for Self Service or some other similar purpose. Is that what this is for? If so - Self-Service-Icon-Maker
Posted on 12-09-2017 05:23 PM
You’re right, splitting it into two lines worked. Not sure what I was thinking using one line and “-p”. Last time I did this I used one line to echo the instruction, one to read input.
Will take a look at your example when I get back from scouting tomorrow’s club ride. I wish I could script a Mustang seat.
Posted on 12-10-2017 07:13 PM
Revisited with a fresh set of eyes, for some reason the read
command chokes when you use it's entire path /usr/bin/read
.
This works:
#!/bin/sh
# Prompt for source file
echo "Drag *.icns file into Terminal window and hit RETURN"
read INPUTFILE
# Prompt for output name
echo "Provide Vendor_Application.png name and hit RETURN"
read OUTPUTFILE
# Create file
/usr/bin/sips --setProperty format png --resampleHeightWidthMax 128 "$INPUTFILE" --out ~/Desktop/"$OUTPUTFILE"
# Open Desktop folder
/usr/bin/open ~/Desktop
exit 0
The same script with the full /usr/bin/read
path fails...no idea why.
¯_(ツ)_/¯
Posted on 12-11-2017 07:41 AM
The same script with the full /usr/bin/read path fails...no idea why.
This may help explain why:
$ cat /usr/bin/read
#!/bin/sh
# $FreeBSD: src/usr.bin/alias/generic.sh,v 1.2 2005/10/24 22:32:19 cperciva Exp $
# This file is in the public domain.
builtin `echo ${0##*/} | tr [:upper:] [:lower:]` ${1+"$@"}
$
Note the use of backquotes around the builtin read command. The backquotes means the shell builtin read command is run in a subshell.
Because the builtin read command assigns the variable inside the subshell, that variable is not accessible to the parent shell, i.e. the shell in which your code is running.
Posted on 12-11-2017 10:52 PM
@mthakur wow, thanks for the heads up, learn something new every day!
I've got to admit this is the first time I've ever got burned by including a full path in a command. :)
https://www.linkedin.com/in/manavendrathakur/