First of all, since nobody else has mentioned this,
the error has nothing to do with cat
.
You would have the same error with any program,
such as nl
, od
, tr
, or even a non-existent command
like dog
unicorn
tribble
1.
The real answer is that you should say <<-
instead of <<
.
As the other answer almost (but not quite) says, the problem is that,
when you use <<
,
the shell looks for the delimiter word (KHIK
in your example)
to be the only thing on the line that terminates the “here document”.
It can’t be FOOKHIKBAR
, FOO KHIK BAR
, KHIK FU
,
or even TabKHIK
.
When you use <<-
, the shell removes all tab(s)
from the beginning of every line in the here document,
so TabKHIK
looks like just plain KHIK
.
But an equally important issue is that, if you say
cat<<KHIK >> run_nvt$i.pbs
#!/bin/bash
#PBS -l nodes=1:ppn=16
#PBS -l walltime=120:00:00
#PBS -N GROMACS:TAUAT_P
#PBS -q blaze
#PBS -j oe
#PBS -V
cd \$PBS_O_WORKDIR
export I_MPI_DEVICE=rdma
/home/apps/ics/impi/latest/bin64/mpiexec.hydra /home/braf/md/gromacs-4.5.6/bin/mdrun_mpi -deffnm conf_nvt$i
KHIK
then you will get
#!/bin/bash
#PBS -l nodes=1:ppn=16
#PBS -l walltime=120:00:00
#PBS -N GROMACS:TAUAT_P
#PBS -q blaze
#PBS -j oe
#PBS -V
cd $PBS_O_WORKDIR
export I_MPI_DEVICE=rdma
/home/apps/ics/impi/latest/bin64/mpiexec.hydra /home/braf/md/gromacs-4.5.6/bin/mdrun_mpi -deffnm conf_nvt{value of $i}
in run_nvt$i.pbs
.
And that’s not good.
For a “shebang” (#!
line) to work correctly,
the #!
must be the first two characters in the line.
If you follow the advice of the other answer,
your run_nvt$i.pbs
script will have a shebang
that is not honored / recognized,
and it might run with /bin/sh
or some other shell (other than bash
) —
see this answer for details.
(Since the first non-blank character of the first line is a #
,
the line will be treated as a comment.
This is an important and often-overlooked aspect of how shebangs work.)
Unrelated to the body of your question —
you should always quote your shell variable references
(e.g., "$i"
and "$PBS_O_WORKDIR"
)
unless you have a good reason not to,
and you’re sure you know what you’re doing;
see Why does my shell script choke on whitespace
or other special characters? and Security implications
of forgetting to quote a variable in bash/POSIX shells.
And you don’t need to use "$PWD"
as often as you think you do —
it’s usually good enough to use .
.
And (IMNSHO) it helps readability to use spaces wherever you can.
So I suggest that you modify your script as follows:
#!/bin/bash
for i in {1..20}
do
cd "conf$i"
cp ../nvt.mdp .
cp ../topol.top .
grompp -v -f nvt.mdp -c conf$i.gro -p topol.top -o "conf_nvt$i.tpr" >> nvt.log
cat <<- KHIK >> "run_nvt$i.pbs"
#!/bin/bash
#PBS -l nodes=1:ppn=16
#PBS -l walltime=120:00:00
#PBS -N GROMACS:TAUAT_P
#PBS -q blaze
#PBS -j oe
#PBS -V
cd "\$PBS_O_WORKDIR"
export I_MPI_DEVICE=rdma
/home/apps/ics/impi/latest/bin64/mpiexec.hydra /home/braf/md/gromacs-4.5.6/bin/mdrun_mpi -deffnm "conf_nvt$i"
KHIK
cd ..
done
Note the spaces before and after the <<-
, and the additional quotes.
A style choice that I like is to indent here documents:
︙
grompp -v -f nvt.mdp -c conf$i.gro -p topol.top -o "conf_nvt$i.tpr" >> nvt.log
cat <<- KHIK >> "run_nvt$i.pbs"
#!/bin/bash
#PBS -l nodes=1:ppn=16
#PBS -l walltime=120:00:00
#PBS -N GROMACS:TAUAT_P
#PBS -q blaze
#PBS -j oe
#PBS -V
cd "\$PBS_O_WORKDIR"
export I_MPI_DEVICE=rdma
/home/apps/ics/impi/latest/bin64/mpiexec.hydra /home/braf/md/gromacs-4.5.6/bin/mdrun_mpi -deffnm "conf_nvt$i"
KHIK
cd ..
︙
I believe that it makes it easier to skim-read the script,
and see which lines are commands that are being executed now,
and which ones are data
(e.g., input to a script, where they may be executed later).
P.S. Don’t you want to do chmod +x "run_nvt$i.pbs"
at some point?
__________
1 Today I learned that there are programs
called dog
and unicorn
.