7

I am following this bash shell scripting guide:

In the section Numeric Comparisons, it cites an example:

anny > num=`wc -l work.txt`

anny > echo $num
201

anny > if [ "$num" -gt "150" ]
More input> then echo ; echo "you've worked hard enough for today."
More input> echo ; fi

What seems to happen above is we store a string of commands in a bash variable and then we invoke echo on the variable. What seems to happen is the string is evaluated and the wc command is executed and returns the line count to the controlling terminal.

Ok, so I launch my terminal in Ubuntu 12.04 and try something similar:

$ touch sample.txt && echo "Hello World" > sample.txt
$ cat sample.txt
Hello World
$ num='wc -l sample.txt'
echo $num
wc -l sample.txt

Wait a second, that didn't evaluate the string and return the line count. That just echoed the string back to the terminal. Why did I get different results?

2

3 Answers 3

5

Please note that symbol:

'

Single quote

   Enclosing characters in single quotes preserves the  literal  value  of
   each character within the quotes.  A single quote may not occur between
   single quotes, even when preceded by a backslash.

and

`

Backquote

   Command substitution allows the output of a command to replace the com‐
   mand name.  There are two forms:

          $(command)
   or
          `command`

   Bash performs the expansion by executing command and replacing the com‐
   mand  substitution  with  the  standard output of the command, with any
   trailing newlines deleted.

So the Backquote is returning result of the command to Standard Output. That is why

`wc -l sample.txt`

returns results of the command, while

'wc -l sample.txt'

just return "wc -l sample.txt" as usual string

Consider doing this as example:

$ A='wc -l /proc/mounts'
$ B=`wc -l /proc/mounts`
$ C=$(wc -l /proc/mounts)

And now echo all three variables:

$ echo $A
wc -l /proc/mounts
$ echo $B
35 /proc/mounts
$ echo $C
35 /proc/mounts
4

If you want to capture the output of a command in a variable, you need to either use backticks `` or enclose the command in $():

$ d=$(date)
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014
$ d=`date`
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014

Note that the string is actually evaluated at the moment of the variable declaration, not when you echo it. The command is actually run within the $() or backticks and the output of that command is saved as the variable's value.

In general, you should always use $() instead of backticks which are deprecated and only around for compatibility reasons and much more limited. You cannot, for example, nest commands within backticks but you can with $():

$ echo $(date -d $(echo yesterday))
Sun Mar 16 10:26:07 CET 2014

See this thread on U&L for some more details of why `` should be avoided.

1
  • 1
    I agree scripts should prefer $( ) to ` `. But as wag says, backquotes do nest. echo $(date -d $(echo yesterday)) becomes echo `date -d \`echo yesterday\``; echo $(echo $(date -d $(echo yesterday))) becomes echo `echo \`date -d \\\`echo yesterday\\\`\``. I say this not rebut your thesis but to strengthen it: escaped internal backquotes make ` ` syntax more powerful than often admitted, but special treatment of \ is weird, surprising, and hard to reason about. With $( ) what you see is usually what you get. Jan 22, 2017 at 2:20
2

You need to use backticks to evaluate the expression.

$ num=`wc -l sample.txt`
$ echo $num
1 sample.txt

If you want to see only "1" in the output, use the command

$ num=`cat sample.txt | wc -l`
$ echo $num
1

And also works:

$ num=`wc -l < sample.txt`
$ echo $num
1

For additional information, see Differences between doublequotes " ", singlequotes ' ' and backticks ´ ´ on commandline?

3
  • Any idea why I get '1 sample.txt' and not just the number '1'? Mar 17, 2014 at 5:20
  • That's the way how wc command works. Try cat sample.txt | wc -l.
    – Danatela
    Mar 17, 2014 at 5:22
  • wc -l displays the number of lines present in a file along with it's filename. Mar 17, 2014 at 5:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .