-2

I am using the following code to write files iteratively in 20 folders for job scheduling.

#!/bin/bash

for i in {1..20}
do
        cd conf$i
        cp ../nvt.mdp $PWD
        cp ../topol.top $PWD
        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

And it is giving out a bizarre error. Can you please tell me what changes I need to make?

./umbrnvt.sh: line 22: warning: here-document at line 9 delimited by end-of-file (wanted `KHIK')
./umbrnvt.sh: line 23: syntax error: unexpected end of file

2 Answers2

7

You should have the close token at the begin of line. So your script should be like:

#!/bin/bash

for i in {1..20}
do
        cd conf$i
        cp ../nvt.mdp $PWD
        cp ../topol.top $PWD
        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 

Otherwise bash will not recognise KHIK as end of the block

Romeo Ninov
  • 17,484
3

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 dogunicorntribble1.

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.