Satish
Satish

Reputation: 17437

for loop run command in from file

I have store commands in file and i want to capture their output, but what is wrong here?

I want to capture output of each command and store in relevant file.

Following just example, i have 100s of command which i want to run and capture optput but i just stuck in my demo testig in following code.

My foo.txt

/bin/ls
/bin/cat /etc/redhat-release

My for loop

[spatel@linux ~]$ IFS=$'\n'
[spatel@linux ~]$ for qw in `cat foo.txt`; do echo $qw; done
backup  bar  final.sh  foo.txt  input.txt
-bash: /bin/cat /etc/redhat-release: No such file or directory

Why /bin/ls run but /bin/cat /etc/redhat-release not run

UPDATE:

[spatel@linux ~]$ /bin/cat /etc/redhat-release
CentOS release 6.6 (Final)

Upvotes: 0

Views: 2909

Answers (4)

John1024
John1024

Reputation: 113844

With your command as shown, neither ls not cat is actually executed:

$ for qw in `cat foo.txt`; do echo $qw; done
/bin/ls
/bin/cat /etc/redhat-release

To get the output that you show, I suspect that you actually ran this command;

$ for qw in `cat foo.txt`; do $qw; done
foo.txt
bash: /bin/cat /etc/redhat-release: No such file or directory

In this case, ls is executed but /bin/cat /etc/redhat-release is not executed because there is no command whose name is the full string /bin/cat /etc/redhat-release. (The shell does not do word-splitting here.)

To see this in a simpler example:

$ ls *.txt
foo.txt
$ a="ls *.txt"; $a
bash: ls *.txt: command not found

Executing all the commands and capturing output to file

To execute all the command in foo.txt, run:

$ bash foo.txt
foo.txt
CentOS release 6.6 (Final)

To run all the commands and capture their output to file output.log, then run:

bash foo.txt >output.log

To run all the commands and show their output on screen while also capturing the output to a file:

$ bash foo.txt | tee output.log
foo.txt
CentOS release 6.6 (Final)

Capturing each command's output to a different file

First, run awk on foo.txt to create foo.sh:

$ awk '{sub(/$/, (" >output" ++count))} 1' foo.txt >foo.sh

This is what foo.sh looks like:

$ cat foo.sh
/bin/ls >output1
/bin/cat /etc/redhat-release >output2

As you can see, each command in the file now has its stdout sent to a numbered file. If you want to capture stderr as well, that is just a small change.

Now, run foo.sh:

$ bash foo.sh
$ cat output1
foo.sh
foo.txt
output1

Upvotes: 3

Walter A
Walter A

Reputation: 20002

You have the commands you want in foo.txt.
How about:

chmod +x foo.txt
./foo.txt > my_output

When this works fine, consider renaming foo.txt into foo.sh.

Upvotes: 0

John
John

Reputation: 3520

What you're looking for is the eval command:

while read qw; do eval $qw; done < foo.txt

The use of eval is strongly frowned upon though, (as it tends to open up lots of security holes).

Another option is to generate a new script file from the original, using sed to attach redirect tags to the end of each line.

Upvotes: 1

hek2mgl
hek2mgl

Reputation: 158010

It happens obviously because the file /etc/redhat-release does not exist.

Btw, if you want to execute commands from a file use a shellscript!

source foo.sh # will execute the commands in the current shell
bash foo.sh   # will launch a new shell to execute the commands

The file extension .sh is not necessary to make it work. but it should being used by convention.

Upvotes: 1

Related Questions