0

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)
1
  • Start a new bash and try again. I can not reproduce your problem. This two lines of code only print content of file foo.txt. Commented May 8, 2015 at 17:58

4 Answers 4

3

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
Sign up to request clarification or add additional context in comments.

4 Comments

With your command as shown, neither ls not cat is actually executed +1 for that! I really wondered after reading the question again...
@satish Yes. The point, however, is that the shell does not do word splitting on $qw: it takes the whole line, not just the first word, as the name of the command.
I got it what you saying, what is the work around? i have many command and i want to capture their output in individual file.
@Satish For a safe way to save the output of each command into a separate file see the last section of the updated answer, the one entitled "Capturing each command's output to a different file".
1

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.

5 Comments

For cutting to the heart of the matter and suggesting that the OP use a script: +1.
file is there /etc/redhat-release see my question, which i updated
I want to capture output of command and store in relevant file
Have you tried to source or execute it as shell script as I've suggested? Probably there are invisible problematic characters in there. For example Windows carriage returns.
I want to capture output of command also like ifconfig > ifconfig.txt that is why i need those command in loop.
1

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.

3 Comments

that works!! what are the security issue with eval?
If someone can manipulate the variable qw, they could append ; rm -rf / to the end of the variable and wipe your system. They could also potentially do things more nasty than that. Which brings up another good point -- you're running commands from foo.txt -- how certain are you that no-one has access to this file?
"eval" is a common misspelling of "evil".
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.