1
#!/bin/sh
if [ $# -lt 1 ]
then echo "error: provide an argument"
exit 1
fi

temp=$(mktemp 2> /dev/null)

wget -o /dev/null -O "$temp" "$1" || { echo "0"; exit 1;}
wc -c < "$temp" 
exit 0

When I remove the 2 in "2>" I get an error, but I want to understand why that occurs. Why is that 2 necessary?

  • 1
    `2` indicates File descriptor 2 is the standard error (stderr). – bigbounty Jul 13 '20 at 07:23
  • @bigbounty right, I got that. However, I don't understand why it is necessary in this case. – Ravi Sangani Jul 13 '20 at 07:25
  • 6
    Without the `2`, `temp=$(mktemp > /dev/null)` will direct the output of the `mktemp` command to /dev/null, leaving nothing for the `$( )` to capture. Therefore, the `temp` variable will be set to the empty string. Apparently, passing a null filename to `wget -O` confuses it, and that causes the error. – Gordon Davisson Jul 13 '20 at 07:32
  • @kaylum `echo $temp` is [not a reliable way to see what the variable contains](https://stackoverflow.com/questions/29378566/i-just-assigned-a-variable-but-echo-variable-shows-something-else). `echo "$var"` or `declare -p temp` would be better, but can still hide some non-printing characters. – Gordon Davisson Jul 13 '20 at 07:33
  • @GordonDavisson thank you for the explanation. there really isn't a reason for mktemp to throw an error so I can just replace that entire line with `temp=$(mktemp)` correct? – Ravi Sangani Jul 13 '20 at 07:41
  • 4
    Actually, I’d recommend something like `temp=$(mktemp) || exit 1` so that, just in case there is an error (it *is* possible for `mktemp` to fail), it’ll exit rather than trying to continue without a valid temp file. – Gordon Davisson Jul 13 '20 at 07:47
  • 1
    @RaviSangani : `mktemp` without any options, as you are using it, _should_ indeed not throw an error, but we can't say it can not throw one. I once was on a machine, where the filessystem for /tmp was overflowing every couple of days, and this would have made `mktemp`fail. I would certainly not suppress error messages from it. The errors may be rare, but **if** there is one, you will be glad to see what happens. – user1934428 Jul 13 '20 at 08:31
  • @GordonDavisson : You are right, that `echo` is not reliable; you would have to hexdump the variable to be sure to know what's in it. However, a mere `mktemp` without any options certainly will not produce unprintable garbage on stdout. – user1934428 Jul 13 '20 at 08:33
  • @user1934428 that is a good example to keep in mind, appreciate the help! – Ravi Sangani Jul 13 '20 at 10:49

1 Answers1

2

2>file means "redirect what's written to file descriptor 2 to the file file". File descriptor 2 is "standard error", the descriptor to which programs write error messages. 2>/dev/null therefore silences error messages.

>file is short for 1>file. It means "redirect what's written to file descriptor 1 to the file file". File descriptor 1 is "standard output", the descriptor to which programs write information messages. >/dev/null therefore silences informational messages.

mktemp writes error messages to stderr. 2>/dev/null silences error messages.

mktemp writes the generated file name to stdout. >/dev/null silences that. (This makes the call to mktemp rather useless!)

For example,

$ alias hello='perl -e'\''print STDOUT "Hello\n"; print STDERR "World\n";'\'''

$ hello
Hello
World

$ hello 2>/dev/null
Hello

$ hello >/dev/null
World

You might want to replace

temp=$( mktemp 2>/dev/null )

with

temp=$( mktemp ) || exit 1

to fail with a useful message rather than passing bad data to wget (which will cause it to fail).

ikegami
  • 367,544
  • 15
  • 269
  • 518