I met a strange problem.
mkfifo "spch2008"
exec 100<>"spch2008"
It's OK. But, when i use variable to replace "100", error occurs.
exec: 100: not found
PIPE_ID=100
mkfifo "spch2008"
exec ${PIPE_ID}<>"spch2008"
I don't know the reason. please hlep me,thanks.
It is caused by shell not performing variable expansion on the left side of the redirection operator. You can use a workaround:
eval exec "${PIPE_ID}"'<>"spch2008"'
It will force the shell to do variable expansion, producing
eval exec 100'<>"spch2008"'
Then the eval built-in will feed the command to the shell, which will effectively execute
exec 100<>"spch2008"
I/O redirection doesn't allow variables to specify the file descriptors generally, not just in the context of the <> redirection.
Consider:
$ cat > errmsg # Create script
echo "$#" >&2 # Echo arguments to standard error
$ chmod +x errmsg # Make it executable
$ x=2
$ ./errmsg Hi # Writing on standard error
Hi
$ ./errmsg Hi ${x}>&1 # Writing on standard error
Hi 2
$ ./errmsg Hi 2>&1 # Redirect standard error to standard output
Hi
$ ./errmsg Hi 2>/dev/null # Standard error to /dev/null
$ ./errmsg Hi ${x}>/dev/null # Standard output to /dev/null
Hi 2
$
Related
I have a variable COUNTRY="INDIA"
and another sets of variables:-
INDIA_POPULATION="5,00,00,000", CHINA_POPULATION="6,00,00,000".
In script I am trying to call them using command:-
echo ${ ${COUNTRY}_POPULATION }
But I am getting bad substitution error. Can someone please tell how to solve it ??
You misplaced a bracket: {$COUNTRY}_POPULATION should be ${COUNTRY}_POPULATION. But even then it would not work as you expect. Use bash indirect expansion:
$ name="${COUNTRY}_POPULATION"
$ echo "${!name}"
5,00,00,000
Or, if you have bash version >= 4.3, you can also use a refname:
$ declare -n name="${COUNTRY}_POPULATION"
$ echo "$name"
5,00,00,000
Motivation
I'm in a situation where I have to run multiple bash commands with a single bash invocation without the possibility to write a full script file (use case: Passing multiple commands to a container in Kubernetes). A common solution is to combine commands with ; or &&, for instance:
bash -c " \
echo \"Hello World\" ; \
ls -la ; \
run_some_command "
In practice writing bash scripts like that turns out to be error prone, because I often forget the semicolon leading to subtle bugs.
Inspired by this question, I was experiment with writing scripts in a more standard style by using a heredoc:
bash <<EOF
echo "Hello World"
ls -la
run_some_command
EOF
Unfortunately, I noticed that there is a difference in exit code error handling when using a heredoc. For instance:
bash -c " \
run_non_existing_command ; \
echo $? "
outputs (note that $? properly captures the exit code):
bash: run_non_existing_command: command not found
127
whereas
bash <<EOF
run_non_existing_command
echo $?
EOF
outputs (note that $? fails to capture the exit code compared to standard script execution):
bash: line 1: run_non_existing_command: command not found
0
Why is the heredoc version behaving differently? Is it possible to write the script in the heredoc style and maintaining normal exit code handling?
Why is the heredoc version behaving differently?
Because $? is expanded before running the command.
The following will output 1, that is the exit status of false command:
false
bash <<EOF
run_non_existing_command
echo $?
EOF
It's the same in principle as the following, which will print 5:
variable=5
bash <<EOF
variable="This is ignored"
echo $variable
EOF
Is it possible to write the script in the heredoc style and maintaining normal exit code handling?
If you want to have the $? expanded inside the subshell, then:
bash <<EOF
run_non_existing_command
echo \$?
EOF
or
bash <<'EOF'
run_non_existing_command
echo $?
EOF
Also note that:
bash -c \
run_non_existing_command ;
echo $? ;
is just equal to:
bash -c run_non_existing_command
echo $?
The echo $? is not executed inside bash -c.
This question already has answers here:
Run bash commands from txt file
(4 answers)
Closed 4 years ago.
I tried to execute commands read it from txt file. But only 1st command is executing, after that script is terminated. My script file name is shellEx.sh is follows:
echo "pwd" > temp.txt
echo "ls" >> temp.txt
exec < temp.txt
while read line
do
exec $line
done
echo "printed"
if I keep echo in the place of exec, just it prints both pwd and ls. But i want to execute pwd and ls one by one.
o/p am getting is:
$ bash shellEx.sh
/c/Users/Aditya Gudipati/Desktop
But after pwd, ls also need to execute for me.
Anyone can please give better solution for this?
exec in bash is meant in the Unix sense where it means "stop running this program and start running another instead". This is why your script exits.
If you want to execute line as a shell command, you can use:
line="find . | wc -l"
eval "$line"
($line by itself will not allow using pipes, quotes, expansions or other shell syntax)
To execute the entire file including multiline commands, use one of:
source ./myfile # keep variables, allow exiting script
bash myfile # discard variables, limit exit to myfile
A file with one valid command per line is itself a shell script. Just use the . command to execute it in the current shell.
$ echo "pwd" > temp.txt
$ echo "ls" >> temp.txt
$ . temp.txt
I have a simple bash script for file listing:
$ cat process.sh
for i in *; do echo $i; done
$
and then I run:
$ ./process.sh
a
b
c
d
process.sh
$
and
$ . ./process.sh
$
and
$ for i in *; do echo $i; done
$
I've read Why does Bash behave differently when called as sh? which explains that inline commands use sh instead of bash - is wildcard non-POSIX in this case?
Why do I get different behaviours when executing the same code?
How to make this example work?
Are there any other cases to look out for?
Solved. The reason was an incorrect for alias. Thanks for your replies.
I am having trouble running the script below (in Cygwin on win 7 mind you).
Lets call it "myscript.sh"
When I run it, the following is what I input:
yearmonth: 2011-03
daypattern: 2{5,6,7}
logfilename: error*
query: WARN
#! /bin/bash
yearmonth=''
daypattern=''
logfilename=''
sPath=''
q=''
echo -n "yearmonth: "
read yearmonth
echo -n "daypattern: "
read daypattern
echo -n "logfilename: "
read logfilename
echo -n "query: "
read q
cat "$yearmonth/$daypattern/$logfilename" | grep --color $q
The output I get is:
cat: /2011-03/2{5,6,7}/error* No such
directory of file exists.
However, if I enter daypattern=25 OR daypattern=26 etc. the script will work.
Also, of course if I type the command in the shell itself, the wildcards are expanded as expected.
But this is not what I want.
I want to be able to PROMPT the user to enter the expressions as they need, and then later, in the script, execute these commands.
Any ideas how this can be possible?
Your help is much appreciated.
Try eval, this should work for the {a,d} and * cases
eval grep --color $q ${yearmonth}/${daypattern}/${logfilename}
Use quote to prevent wildcard expansion:
$ a="*.py"
$ echo $a
google.py pair.py recipe-523047-1.py
$ echo "$a"
*.py