Scripting with executables

Hi everyone,

I am working with an executable (let's say work) in bash shell. When I run this work
executable it asks the following information;
1- choose task a or b
2- input file
3- output file
4- some operational choices

after it reads the given input file, does some algebraic operations with the input files data and
writes to the given output file. The question is the following, I need to run this executable many times with large number of input files, for each time my answers and choices are the same. So how can I run everything in one single script.

./work a input.file output.file choices

this command does not work, evidently the work executable can not read arguments.

any help will be highly appreciated.

Post some examples of what the prompts(i.e. questions) look like on your screen that the application prompts you with, you probably can do what you want with "expect".

I have the source code of executable

here are the relevant parts where it prompts on the screen:

1st prompt;

      
write(*,*)
write(*,*) '  Input run mode:'
write(*,*) '  ---------------'
write(*,*)
write(*,*) '  0 = calculates decay widths'
write(*,*) '  1 = decay events in file'
write(*,*)

read(*,'(i1)')  run_mode

2nd prompt;

write(*,*) 'input event file: (e.g. events.lhe)'
read(*,'(a)')  infile

3rd prompt;

write(*,*) 'name for output file: (e.g. dec-events.lhe)'
read(*,'(a)')  outfile

4th prompt;

write(*,*) ' Implemented decays are for:'
write(*,*) ' ---------------------------'
write(*,*)
write(*,*) ' Leptons: ta- ta+' 
write(*,*) ' Quarks : t t~' 
write(*,*) ' Bosons : z w+ w- h'        
write(*,*) ' Input particle to be decayed (e.g. t~):'
read(*,'(a3)',err=99)  name

5th prompt;

if(ip.eq.15) then  ! tau-
string(1) =  ' ta- -> vt   e- ve~  '
string(2) =  ' ta- -> vt  mu- vm~  '
string(3) =  ' ta- -> vt   l- vl~ (e+mu) '
string(4) =  ' ta- -> vt   pi-     '
string(5) =  ' ta- -> vt  rho(770)-'
write(*,'(i2,2x,a30)') (i,string(i),i=1,5)
write(*,*) ' '
write(*,*) 'your choice is:'   
read (*,*) imode

I tried to replace the 2nd argument of read statements with $1, $2, $3 etc. and recompiled. But it complains at the compilation level.

Hi.

It's useful if you post your OS and language with your question.

Your program is clearly Fortran.

I'll assume that you want to change your program as little as possible. With that assumption, here are some techniques for entering data that is requested with read(*,*) statements:

#!/usr/bin/env bash

# @(#) s1	Demonstrate data input into Fortran.

# Utility functions: print-as-echo, print-line-with-visual-space, debug.
# export PATH="/usr/local/bin:/usr/bin:/bin"
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
db() { ( printf " db, ";for _i;do printf "%s" "$_i";done;printf "\n" ) >&2 ; }
db() { : ; }
C=$HOME/bin/context && [ -f $C ] && $C gfortran

VALUE=${1-17.4}

pl " Script value argument: $VALUE"

pl " Sample choices text file inputs:"
head choices*

pl " Demonstration Fortran code:"
F=f2.f90
cat $F

# Compile code.
pe
gfortran $F
file a.out

pl " Execute, enter data from keyboard:"
./a.out

pl " Execute, read from choices-1:"
./a.out < choices-1.txt

pl " Execute, read from choices-2:"
./a.out < choices-2.txt

pl " Execute, read from in-line data, a \"here\" document:"
./a.out <<SIGNAL
97
SIGNAL

pl " Execute, read from in-line data, a \"here\" document, script parameter:"
./a.out <<CHEWING_GUM
$VALUE
CHEWING_GUM

exit 0

producing:

./s1 101.55

Environment: LC_ALL = C, LANG = C
(Versions displayed with local utility "version")
OS, ker|rel, machine: Linux, 2.6.26-2-amd64, x86_64
Distribution        : Debian GNU/Linux 5.0.8 (lenny) 
bash GNU bash 3.2.39
gfortran GNU Fortran (Debian 4.3.2-1.1) 4.3.2

-----
 Script value argument: 101.55

-----
 Sample choices text file inputs:
==> choices-1.txt <==
33

==> choices-2.txt <==
67.24

-----
 Demonstration Fortran code:
program f2

! @(#) f2	Demonstrate Fortran-90.

write(*,*) " First number:"
read(*,*) x
write(*,*) " You entered: ", x

end program f2

a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.8, not stripped

-----
 Execute, enter data from keyboard:
  First number:
22
  You entered:    22.000000    

-----
 Execute, read from choices-1:
  First number:
  You entered:    33.000000    

-----
 Execute, read from choices-2:
  First number:
  You entered:    67.239998    

-----
 Execute, read from in-line data, a "here" document:
  First number:
  You entered:    97.000000    

-----
 Execute, read from in-line data, a "here" document, script parameter:
  First number:
  You entered:    101.55000

There are standard modules that one can call to process the control statement. They might be of use in processing the file arguments. However, it would be useful if you would post the code for initializing the input and output files: where the filenames are defined, the open & close statements, etc.

Best wishes ... cheers, drl

Hi drl,

thanks for your suggestion, but I could not completely understand your solution and I don't think it will solve my problem. Let me tell you in this way; my answers for prompt questions are the same for all files,
so I would like to run my executable with arguments so that it will not be disturbed during its operation;
simply like

./work 1 events.lhe dec-events.lhe ta- 2

I can send you the whole source code, but there is no attach option here. I don't want to paste all here since it is a bit long. My OS is OpenSUSE and the language is Fortran for sure.

thanks for your help.

Hi.

Yes, I understand your desire to use the same set of parameters with different datasets. The demo script showed different ways to get the parameters into the program without changing the code, and without repeatedly requiring interactive input.

However, to continue I need to know how the code handles the data files.

Please post the (presumably) small sections of the code that opens the input and output files ... cheers, drl

      open(lunr,file=infile,status='old')
      open(lunw,status='scratch')
      open(luni,file=outfile,status='unknown')
c
c     copy old banner into new banner and the param_card.dat into the scratch file
c
      done=.false.
      lwrite=.false.
      newbanner=.false.
      read(lunr,'(a132)',err=99) buff
      do while(index(buff,'<init>') .eq. 0)
         if(index(buff,"<header>") .ne. 0) newbanner=.true.
         if (index(buff,"<slha>") .ne. 0 .or.
     $        index(buff,"Begin param_card.dat") .ne. 0) lwrite=.true.
         if (index(buff,"</slha>") .ne. 0 .or.
     $        index(buff,"End param_card.dat") .ne. 0) lwrite=.false.
c         
         if(index(buff,'</header>') .eq. 0 .and.
     $        (newbanner .or. index(buff,'-->') .eq. 0 ))
     $      write(luni,'(a)') buff(1:len_trim(buff))
         if(lwrite) write(lunp,'(a)') buff(1:len_trim(buff))
c         if(lwrite) write(*,'(a50)') 'found in param_card: ',buff
c         if(.not.lwrite) write(*,'(a50)') 'found in banner: ',buff
         read(lunr,'(a132)',err=99) buff
      enddo
c
      rewind(lunr)
c
      endif

here it is where it opens input and output files.

Hi.

OK, good, thanks.

Now where are the variables infile and outfile set (defined, assigned, given a value, etc.) Please post that code ... cheers, drl

here is where they are defined

      character*70 infile,outfile
      integer run_mode
      common/mode/run_mode,infile

Hi.

OK, now where and how are they set with a value? ... cheers, drl

      write(*,*) 'input event file: (e.g. events.lhe)'
      read(*,'(a)')  infile
c
      write(*,*) 'name for output file: (e.g. dec-events.lhe)'
      read(*,'(a)')  outfile

Hi.

Here is a sample script that simulates running your Fortran program with 3 pairs of filesnames, but all the remainder of the data is the same.

If the output looks something like you want it to, then I'll post the skeleton Fortran code.

#!/usr/bin/env bash

# @(#) do-all-files	Processing with static data, but different pairs of files.

pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
db() { ( printf " db, ";for _i;do printf "%s" "$_i";done;printf "\n" ) >&2 ; }
db() { : ; }
C=$HOME/bin/context && [ -f $C ] && $C gfortran

FILE=${1-"file-pairs"}

pl " File of input, output filename pairs, $FILE:"
head $FILE

i=1
pl " Processing pairs of files:"
while read input output
do
echo 
echo "-----"
echo " Iteration $i"
echo
./a.out <<EOF
3
$input
$output
rho
5
EOF
i=$( expr $i + 1 )
done < <( cat $FILE )

exit 0

producing:

% ./do-all-files 

Environment: LC_ALL = C, LANG = C
(Versions displayed with local utility "version")
OS, ker|rel, machine: Linux, 2.6.26-2-amd64, x86_64
Distribution        : Debian GNU/Linux 5.0.8 (lenny) 
bash GNU bash 3.2.39
gfortran GNU Fortran (Debian 4.3.2-1.1) 4.3.2

-----
 File of input, output filename pairs, file-pairs:
i1 o1
input-2 output-2
in_3.txt out_3.txt

-----
 Processing pairs of files:

-----
 Iteration 1


   Input run mode:
  Run mode is            3

 input event file: (e.g. events.lhe)
  input is i1                            

 name for output file: (e.g. dec-events.lhe)
  output is o1                            

  Input particle to be decayed (e.g. t~):
  particle is rho                           

 1   ta- -> vt   e- ve~           
 2   ta- -> vt  mu- vm~           
 3   ta- -> vt   l- vl~ (e+mu)    
 4   ta- -> vt   pi-              
 5   ta- -> vt  rho(770)-         
 your choice is:
  mode is:           5

-----
 Iteration 2


   Input run mode:
  Run mode is            3

 input event file: (e.g. events.lhe)
  input is input-2                       

 name for output file: (e.g. dec-events.lhe)
  output is output-2                      

  Input particle to be decayed (e.g. t~):
  particle is rho                           

 1   ta- -> vt   e- ve~           
 2   ta- -> vt  mu- vm~           
 3   ta- -> vt   l- vl~ (e+mu)    
 4   ta- -> vt   pi-              
 5   ta- -> vt  rho(770)-         
 your choice is:
  mode is:           5

-----
 Iteration 3


   Input run mode:
  Run mode is            3

 input event file: (e.g. events.lhe)
  input is in_3.txt                      

 name for output file: (e.g. dec-events.lhe)
  output is out_3.txt                     

  Input particle to be decayed (e.g. t~):
  particle is rho                           

 1   ta- -> vt   e- ve~           
 2   ta- -> vt  mu- vm~           
 3   ta- -> vt   l- vl~ (e+mu)    
 4   ta- -> vt   pi-              
 5   ta- -> vt  rho(770)-         
 your choice is:
  mode is:           5

Let me know ... cheers, drl

Hi drl,

this is kind of what I want, do you parse the arguments in command line or you simply embed them in your code?

Hi.

These are in a "here document". You can place $1, $2, etc., into the here document if you wanted. Notice that I read a file of filename pairs and placed those variables in the here document.

The reason I used the here document is that the Fortran was coded to read from STDIN (usually the keyboard), so using the here document avoids changing the Fortran.

How would you *like* it to be executed -- what would be a typical run, with (if I understand you) a few input and output files? My understanding is that you wanted to keep the other settings (parameters) constant for a series of runs.

Best wishes ... cheers, drl

That's fine, and here is what I really want for how to execute,
the fortran program is called as work, so I run it as ./work and it prompts.
I would like to parse arguments as follows

./work 1 events.lhe dec-events.lhe ta- 5

so I either need to modify the original fortran program (work) or need another simple script (lets say script executable) which reads arguments from command line as above and use work executable to operate with its arguments.

./script 1 events.lhe dec-events.lhe ta- 5

where the arguments are;
1st argument -> run_mode =1
2nd argument -> infile = events.lhe
3rd argument -> outfile = dec-events.lhe
4th argument -> decaying particle -> ta-
5th argument -> decay mode -> 5

Hi.

OK, I think I understand. Usually scripts that manipulate and do some parameter processing are called wrappers, which is what the last script do-all-files was.

I'll work on the new wrapper, probably later this morning or early afternoon ... cheers, drl

---------- Post updated at 10:26 ---------- Previous update was at 09:30 ----------

Hi.

Here is script s2. It's a driver for wrapper script "w1", which collects the command-line arguments and places them in a here document for Fortran-compiled code "work" to process. Of course, "work" is a simulation of your program, it just reads and prints the input parameters from STDIN (usually the keyboard, but now from the here document), no calculations are done.

#!/usr/bin/env bash

# @(#) s2	Demonstrate wrapper script "w1" for executable "work".

echo
echo "-----"
echo " Content of wrapper script w1:"
head -20 w1
echo "-----"

echo
echo " Results from run:"
echo " -----------------"
echo

./w1 1 events.lhe dec-events.lhe ta- 5

exit 0

producing:

% ./s2

-----
 Content of wrapper script w1:
#!/usr/bin/env bash

# @(#) w1	Process command-line options for STDIN Fortran.

./work <<EOF
$1
$2
$3
$4
$5
EOF

exit 0
-----

 Results from run:
 -----------------

   Input run mode:
  Run mode is            1

 input event file: (e.g. events.lhe)
  input is events.lhe                    

 name for output file: (e.g. dec-events.lhe)
  output is dec-events.lhe                

  Input particle to be decayed (e.g. t~):
  particle is ta-                           

 1   ta- -> vt   e- ve~           
 2   ta- -> vt  mu- vm~           
 3   ta- -> vt   l- vl~ (e+mu)    
 4   ta- -> vt   pi-              
 5   ta- -> vt  rho(770)-         
 your choice is:
  mode is:           5

Please look this over, try to understand it, and apply to your Fortran code work.

Best wishes ... cheers, drl

1 Like

so where is w1 wrapper script?

---------- Post updated at 11:18 AM ---------- Previous update was at 10:48 AM ----------

Hi drl,

I finally figured it out from your solution, the following was simply what I exactly wanted :slight_smile:

./a.out <<EOF
3
$input
$output
rho
5
EOF

I think I messed it up a bit while explaining things, but anyways thank you very much for your help. I do appreciate.

Cheers.

Hi.

OK, you're welcome. Good luck ... cheers, drl