Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I ran into this interesting issue while populating my WM bar with info text, which is applied by setting the root window's title, i.e. xsetroot -name "clever words"

To this end, printing a fortune works fine in a terminal:

fortune -s | while read -r; do xsetroot -name "$REPLY"; done

Yet that same fails when run from a shell script:

#!/bin/sh
cat /tmp/afile | while read; do echo "$REPLY"; done

Produces:

$ sh afilereader
afilereader: 2: read: arg count

Of course this is remedied by assigning our fortune result to a variable, then using xsetroot with said variable. But I'd still like to understand why this does not work in a script.

I realize each command on either side of the pipeline is run within it's own subshell, but fail to see how their localized variables could affect the while read loop. Or are variables out of scope even between the loop iterations?

What am I missing?

Update: The sh I used is linked to dash, which is in the process of being made POSIX compliant. Using the more venerable bash solved this.

share|improve this question
    
dash's behavior here doesn't manifest any falling short of POSIX compliance. POSIX doesn't require that the read be invocable without a variable: pubs.opengroup.org/onlinepubs/9699919799/utilities/read.html –  dubiousjim Nov 13 '12 at 11:55
add comment

2 Answers

up vote 5 down vote accepted

You appear to be running the first example in bash, and the second in whatever is pointed to by /bin/sh, which is a POSIX shell requiring an argument to be passed specifying the variable you wish to put the input into. Changing the shebang to #!/bin/bash should fix this.

share|improve this answer
    
Good observation @Chris! That works. Think I will read up a bit on the difference between sh and bash. –  invert Nov 12 '12 at 18:32
    
Abnormal indeed! I could relink /bin/sh to bash, but think I'd just use bash directly from now on, to avoid ambiguity. Thanks :) –  invert Nov 12 '12 at 18:46
add comment

In sh syntax, you need

IFS= read -r REPLY

Some shells like ksh, bash and zsh allow read to be called without a variable name but the behavior differs between them. See for instance the output of

printf 'te\ st\\\na ' | "$shell" -c 'read; printf "%s\n" "<$REPLY>"'

differing on all of bash, zsh, pdksh and ksh93

share|improve this answer
    
That makes sense why the shell I was using didn't know the variable name, thanks @Stephane. –  invert Nov 12 '12 at 19:33
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.