3

I have file.txt with command stored in one line (this command is valid when running in console) and I want to execute it in one line with sh like

cat file.txt | eval

what is missing? any protips?

and what if I have file with many commands (one for each line) and I want to execute only one command (one whole line)? my first idea is:

head -n5 | tail -n1 | eval
  • possible duplicate of cat line X to line Y on a huge file – HalosGhost Jun 21 '14 at 16:34
  • Though there is a slight twist, what you're looking for appears to be very similar to extracting part of a file (which has been covered in several questions, e.g., here. – HalosGhost Jun 21 '14 at 16:36
  • What's the point, as opposed to just executing the file? – l0b0 Jun 21 '14 at 16:47
13

eval does not read its command string from stdin.

eval "$(cat file.txt)"
# or easier, in ksh/bash/zsh
eval "$(<file.txt)"
# usually you cannot be sure that a command ends at the end of line 5
eval "$(head -n 5 file.txt)"

Instead of eval you can use standard . or bash/zsh/ksh source if the commands are in a file anyway:

source ./file

(note that it's important to add that ./. Otherwise source looks for file in $PATH before considering the file in the current directory. If in POSIX mode, bash would not even consider the file in the current directory, even if not found in $PATH).

That does not work with choosing a part of the file, of course. That could be done by:

head -n 5 file.txt >commands.tmp
source ./commands.tmp

Or (with ksh93, zsh, bash):

source <(head -n 5 file.txt)
1

so... a solution to your question is 100% possible, and (in the context of make) important.

I ran into this with a makefile, and given the difficulty of nesting bash commands in a makefile which already uses $(...) to call variables, it is nice to be able to do exactly what you are asking about.

Rather than using eval, just use awk or perl's system command:

// command_list.sh:
echo "1"
echo "2"
echo "3"

// command line prompt:
$: cat command_list.sh | awk '{system($0)}'
1
2 
3

And, command building:

// a readable version--rather than building up an awk miniprogram, 
// split into logical blocks:

$: cat inputs.txt | awk '{print "building "$1" command "$2" here "}' | awk '{system($0)}' 
  • Beware that this runs the commands in a separate bash instance, so if you are trying to do something like set variable values, this will fail in such a case. – b_laoshi Mar 1 at 0:36
  • @b_laoshi well it won’t set the variables globally, if that is what you mean by “fail”. You would be better off “source”ing a config.sh file than nesting variable declarations in a nested shell. – donlan Mar 1 at 7:02
  • @b_laoshi anyhow, this problem is the same problem as running with a bash file—see this answer: stackoverflow.com/questions/1464253/… – donlan Mar 1 at 7:07
  • Yes, I see that, but that's not the point of my comment. The point is that this is solution as is will fail when simply trying to set variables. It's far simpler to take Hauke Laging's approach when setting variables or running any command that needs to run in the same shell instance. – b_laoshi Mar 4 at 0:26
  • @b_laoshi ah, so you are marketing a different question? Or is your point just a non sequitor? – donlan Mar 5 at 11:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.