1

I have a Fortran program which save a file (fort.111) each time the program (./test) is called.

I create another program (main.f90) which use EXECUTE_COMMAND_LINE statement to move the fort.111 file to another file each time this second program is launched.

The skeleton should be:

  1. launch './main' which launches './test' -> give me the fort.111 file
  2. I move fort.111 to another file #.dat
  3. Repeat the do-loop in main N times.

This should give me N file.dat from let's say 1.dat to N.dat.

My attempt is, for the test.f90 program:

program test
implicit none

!! Create a file named fort.111 each time is launched
open(unit=20,file='fort.111')

write(20,*) 'I am the program called by main!'

close(20)

end program test

And for the main program:

program main
implicit none

integer :: i
integer, parameter :: n = 1158

call EXECUTE_COMMAND_LINE("COUNTER=0") ! initialize the counter
do i = 1,n
   call EXECUTE_COMMAND_LINE("./test") ! launch the program ./test
   call EXECUTE_COMMAND_LINE("COUNTER=$((COUNTER + 1))") ! update the counter
   call EXECUTE_COMMAND_LINE("mv fort.111 $COUNTER.dat") ! mv the file to the new one
end do

end program main

The problem is in the mv command since I can't figure out how to move fort.111 to 1.dat and pass to the next one (i.e.: fort.111 -> 2.dat, fort.111 -> 3.dat ...)

  • 1
    This is not Fortran 90, but Fortran 2008. – Vladimir F Героям слава Oct 17 '16 at 20:28
  • Each call to `EXECUTE_COMMAND_LINE` is in a new, different, shell process, so adding to a shell variable like that would have no residual effect. – cdarke Oct 17 '16 at 21:35
  • @HighPerformanceMark Because I have the .exe of the first program I can't modify it . I know how it works but I don't have the complete source. – Panichi Pattumeros PapaCastoro Oct 18 '16 at 15:46
  • 2
    I've re-opened this question. I don't think it is a duplicate of the one it was supposed to be a duplicate of. The point is not that OP has failed to understand how to write integers into strings, but that OP has failed to understand that the conversion must be done in Fortran prior to sending the string to the shell for execution. – High Performance Mark Oct 19 '16 at 13:12
  • The answers to http://stackoverflow.com/questions/40117357/list-the-content-of-a-directory-specified-by-loop-indices may be of use. – High Performance Mark Oct 21 '16 at 06:13

1 Answers1

1

the problem is that every EXECUTE_COMMAND_LINE that you run is executed in a separate shell. So basically $COUNTER is empty when you call your mv command.

9.93 EXECUTE_COMMAND_LINE — Execute a shell command

Description: EXECUTE_COMMAND_LINE runs a shell command, synchronously or >asynchronously.

The COMMAND argument is passed to the shell and executed, using the C >library's system call. (The shell is sh on Unix systems, and cmd.exe on >Windows.)

Bad alternatives:

  • Try to set the COUNTERenvironment variable to the value that's in i, unfortunately, it doesn't seem possible from Fortran. Maybe from a C import? I'm no Fortran specialist, 5 minutes ago I couldn't even write it with the proper case :)
  • Why not composing the mv command line from Fortran directly using i? That would be the cleanest way. Easier said than done, though, given Fortran limited string formatting. But there are routines that can handle it for you, example: http://www.gbenthien.net/strings/index.html
  • Last option: you could generate a temporary bash string containing all the commands in a temporary directory, and then EXECUTE_COMMAND_LINE that.

Edit: Avoiding the XY problem

Why not creating a simple loop in a bash shell for that? The one below will do what you need, no need to bother Fortran for that:

n=1158

COUNTER=0
while [ $COUNTER -lt $n ] ;
do
   ./test
   COUNTER=$((COUNTER+1))
   mv fort.111 $COUNTER.dat
done

or as roygvib proposed with a for loop which is more logical in that context since there's no exit condition and counter increasing:

n=1158; for (( i = 1; i <= n ; i++ )) ; do ./test ; mv fort.111 $i.dat ; done

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219