`do' unexpected -> Error message

Hi Folks,

I got the below given error message while i try to run the script.

!/bin/bash
echo 9.9
`for dir in \ `logins -ox | awk -F: '($8 == "PS") { print $6 }'`; do 
find ${dir}/.netrc -type f \( \
 -perm -g+r -o -perm -g+w -o -perm -g+x -o \ 
-perm -o+r -o -perm -o+w -o -perm -o+x \) \ 
-ls 2>/dev/null 
done`

error message:

9.9.sh: line 3: syntax error at line 3: `do' unexpected
9.9.sh: line 3: syntax error at line 3: `for' unmatched

----------------------------------
Am I missing something ???

For starters:

  1. she-bang line starts with a hash symbol #! /bin/bash
  2. The entire for loop is in backticks. Whyyyyy??????

Dont use backquotes for a for statement.
Instead of:

`for dir in \ `logins -ox | awk -F: '($8 == "PS") { print $6 }'`; do 

Try:

for dir in logins -ox | awk -F: '($8 == "PS") { print $6 }'; do 

hth

Hi Sea,

Now, I got the below error message:

test.sh: line 3: syntax error at line 3: `|' unexpected

Right, happend during review ^^

if its bash, its suggested to use $() rather than `` .
So it'll be:

$(logins -ox | awk -F: '($8 == "PS") { print $6 }')

One can simplify to:

for ITEM in $LIST
do <stuff>
done

$LIST can be expanded to anything that be output'ed from within a $() or `` , just as you do.
Depending on the content of imagined $LIST, you would need to put quotes around: "$( code )" .
Saying: Quoteing is just around the $LIST , not around the for .

hth

As it is: yes. You have been given ample help already on how to construct the for-loop syntactically correct. IMHO this is one side of the story. My advice is to avoid for-loops for things like yours altogether and use while-loops instead:

instead of

for VAR in $(command -producing | some | list) ; do
     something $VAR
done

do

command -producing | some | list |\
while read VAR ; do
     something $VAR
done

There are two reasons for this:

first, "for" parses words, not lines. If one of the list of items the command produces contains a whitespace it will break. The "while read ..." will parse on lines and as long as on each line is only one value you are fine even if the values themselves contain whitespace.

second, there is a maximum line length and a maximum number of arguments a command can take in place. These values have been increased with the advent of 64-bit OSes but they are still there and whatever you feed into "for" is an argument to it. For instance:

 for i in 1 2 3 4 5 ; do .... done

gives 5 arguments, "1", "2", etc., to "for". Because your process substitution ("$(...)" or backticks) can produce any number of arguments without you having control over the process. It may never really hit you but why the take the risk? The while-loop will have no restriction in the number of elements it can process because it handles one item at a time.

I hope this helps.

bakunin