Help with "read" command

donmontalvo
Esteemed Contributor III

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?

--
https://donmontalvo.com
1 ACCEPTED SOLUTION

donmontalvo
Esteemed Contributor III

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.

¯_(ツ)_/¯

--
https://donmontalvo.com

View solution in original post

5 REPLIES 5

mm2270
Legendary Contributor III

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

donmontalvo
Esteemed Contributor III

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.

--
https://donmontalvo.com

donmontalvo
Esteemed Contributor III

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.

¯_(ツ)_/¯

--
https://donmontalvo.com

mthakur
Contributor

@donmontalvo

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.

donmontalvo
Esteemed Contributor III

@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. :)

d05ef3221f6d4f5fbe16d4bdf5499312

https://www.linkedin.com/in/manavendrathakur/

--
https://donmontalvo.com