Judking
Judking

Reputation: 6371

How to read commands from a file and execute them?

The content of 'cmds.txt' is as follow:

ssh -o "StrictHostKeyChecking no" [email protected] "/usr/bin/whoami"
ssh -o "StrictHostKeyChecking no" [email protected] "/usr/bin/whoami"
ssh -o "StrictHostKeyChecking no" [email protected] "/usr/bin/whoami"
ssh -o "StrictHostKeyChecking no" [email protected] "/usr/bin/whoami"
ssh -o "StrictHostKeyChecking no" [email protected] "/usr/bin/whoami"

I'm trying to iterate through this file in prompt and execute them respectively. My command is:

export IFS=$'\n'; for i in `cat cmds.txt`; do $i; done

But it complains bash: ssh -o "StrictHostKeyChecking no" [email protected] "/usr/bin/whoami": No such file or directory.

Is there anything I'm missing? Thanks a lot.

Upvotes: 2

Views: 155

Answers (4)

Jahid
Jahid

Reputation: 22428

Putting commands in variables isn't a good idea, but if you want to do it any way, then you can do this:

while IFS= read -r line; do
${line[*]}
done <cmds.txt

Note: Don't use quotes in variable $line ( "$line" or "${line[*]}" ). It won't work for this case.

One way to use your existing code while avoiding using eval might be:

IFS=$'\n'
for i in `cat cmds.txt`; do #use of $(<cmds.txt) is better than `cat cmds.txt`
bash <<EOF
${i[*]} 
EOF
done

Note: using cat and for to read line from file isn't recommended, use while loop instead.

Upvotes: 0

tripleee
tripleee

Reputation: 189317

Don't put entire commands in variables and don't loop over lines with for. The simple and straightforward solution is to factor out only those parameters which actually vary.

while read user_host; do
    ssh -o "StrictHostKeyChecking no" "$user_host".myhost.cn /usr/bin/whoami
done <<'____HERE'
    adamH@K1201
    alexB@K1202
    adamR@K1203
    kevinC@K1204
    rajE@K1205
____HERE

Upvotes: 4

Barmar
Barmar

Reputation: 780724

Since you've set IFS to just a newline, when it does word splitting on $i it only splits it at newlines, the spaces are no longer treated as delimiters. So the entire line is taken as the command name, not a command followed by arguments.

But if you fix that, it still won't work, because quotes are not processed after expanding a variable. You need to use eval to put it through all the rules of command parsing.

IFS=$'\n'; for i in `cat cmds.txt`; do eval "$i"; done

But instead of using for and having to set IFS, you could do:

while read -r i; do eval "$i"; done < cmds.txt

Upvotes: 2

chaos
chaos

Reputation: 9272

Why don't you just use source?

source cmds.txt

Or even shorter:

. cmds.txt

Upvotes: 3

Related Questions