3

I don't understand what does the dollar sign do. Especially in this context:

for url in  $(cat   example.txt);   do  host    $url;   
Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
HackerN
  • 51
  • Thank you so much. So, to just confirm I understand this correctly. the first dollar sign get the output of the file and then I am kinda not sure about the second $ sign? is that part of the for loop directions? Also, not sure what does host do in this example. – HackerN Sep 03 '17 at 00:09
  • This has nothing to do with your question, but you should not use for to read lines of text. You can use a while loop to accomplish that kind of tasks: while read -r url; do host "$url"; done < example.txt – nxnev Sep 03 '17 at 02:41

3 Answers3

6

Bash Reference Manual Bash Manual

3.2.4.3 Grouping Commands

Bash provides two ways to group a list of commands to be executed as a unit. When commands are grouped, redirections may be applied to the entire command list. For example, the output of all the commands in the list may be redirected to a single stream.

()

( list )

Placing a list of commands between parentheses causes a subshell environment to be created (see Command Execution Environment), and each of the commands in list to be executed in that subshell. Since the list is executed in a subshell, variable assignments do not remain in effect after the subshell completes.

This is different with the $ because it then becomes command substitution:

3.5.4 Command Substitution

Command substitution allows the output of a command to replace the command itself. Command substitution occurs when a command is enclosed as follows:

$(command)

3.2.4.1 Looping Constructs

for

The syntax of the for command is:

for name [ [in [words …] ] ; ] do commands; done

Expand words, and execute commands once for each member in the resultant list, with name bound to the current member. If ‘in words’ is not present, the for command executes the commands once for each positional parameter that is set, as if ‘in "$@"’ had been specified (see Special Parameters). The return status is the exit status of the last command that executes. If there are no items in the expansion of words, no commands are executed, and the return status is zero.

Lets say your example.txt contains the following:

www.google.com
www.youtube.com
www.facebook.com

Your command will do the following:

url=www.google.com
host www.google.com

url=www.youtube.com
host www.youtube.com

url=www.facebook.com
host www.facebook.com

host is a command that returns a URL's IP address.

jesse_b
  • 37,005
2

That is command substitution syntax. It takes the command inside the parenthesis, runs it, then takes the output (standard output) from that command and replaces it into that part of the command string. The tricky part about relying on it in this example is twofold:

  1. since it's not quoted, the results will be subject to filename expansion (so if any part of example.txt contains a pattern that matches existing filenames, you'll get those filenames instead of the pattern/string), and
  2. the results are split into words according to the $IFS variable. If example.txt contains a filename like "a filename.txt" then the outer for loop will see two parameters -- a and filename.txt and likely do the Wrong Thing.

You see this example frequently as people rely on the contents of example.txt to not contain filename patterns or spaces (or tabs).

The upshot of this oneliner is to loop over presumed domain names in example.txt and do DNS lookups on them.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
2

For understanding bash code it is usually very helpful to set the -x option:

set -x # within a script / function

or when calling a script:

bash -vx ./script.sh

With loops this is a little less helpful. But you can always take the first part of the command and do this:

echo for url in  $(cat   example.txt)

That shows you what happens there (at least the result).

This feature is called "command substitution". It replaces the $(...) with the output of the command(s) withing (without trailing newlines).

bash -n ./script.sh shows you syntax errors. It would have pointed you at the missing done at the end of your code.

Hauke Laging
  • 90,279