3

How can I copy a file in fortran 90 in a portable, cross plaform way ?

Stefano Borini
  • 138,652
  • 96
  • 297
  • 431

6 Answers6

1

Use the SYSTEM with your OS's copy command. Practically all compilers support this feature.

Rook
  • 60,248
  • 49
  • 165
  • 242
  • @Stefano Borini - Since when? – Rook Mar 02 '11 at 15:07
  • @Rook : since when `cp` does not exist on windows and I don't want to have my code decide which platform is running on in order to invoke `copy` instead of `cp`. – Stefano Borini Mar 02 '11 at 15:09
  • 1
    @Stefano Borini - Ah, a perpetuum mobile seeker. Good luck then. The rest of us have no problem with that. – Rook Mar 02 '11 at 15:11
  • @Rook: because you don't have to support windows ? – Stefano Borini Mar 02 '11 at 15:15
  • @Stefano Borini - I support windows as well. – Rook Mar 02 '11 at 15:28
  • @Rook : so how do you invoke depending on OS ? – Stefano Borini Mar 02 '11 at 15:51
  • Either use the above with the regular copy command, test whether it reports an error and if it does use the alternative, or use the cp exclusively (from those unix toolkits compiled natively for windows) and distribute it with your program. Either approaches work well. – Rook Mar 02 '11 at 17:26
  • I have a small unix kit of some sort that I'm using for that purpose; cannot seem to find the link now where I got it from. If you need it, yell away, and I'll try to find it. – Rook Mar 02 '11 at 17:27
  • @Stefano - One more solution that occured to me later (if you really want a portable solution within reason) is to use perl (or python, if that is your flavour) for such ops. That way you don't have to trouble yourself with testing for platform. I doubt you're working on any platform which doesn't have perl implementation of some kind. – Rook Mar 04 '11 at 00:19
1

You can read/write the file through a stream in Fortran 2003, but in Fortran 90/95 I think this would work to copy an arbitrary file (extremely inefficient though!!)

OPEN(UNIT=ISRC, FILE='', ACCESS='DIRECT', STATUS='OLD', ACTION='READ', IOSTAT=IERR, RECL=1)
OPEN(UNIT=IDST, FILE='', ACCESS='DIRECT', STATUS='REPLACE', ACTION='WRITE', IOSTATE=IERR, RE)
IREC = 1
DO
  READ(UNIT=ISRC, REC=IREC, IOSTAT=IERR) CHAR
  IF (IERR.NE.0) EXIT
  WRITE(UNIT=IDST, REC=I) CHAR
  IREC = IREC + 1
END DO

Of course, if it was a fortran generated file, you could use that information to make it more efficient.

On a personal note: if you need invoke system calls from inside fortran, what are you doing? Isn't it better to use some other language that is better suited for the task?

steabert
  • 6,540
  • 2
  • 26
  • 32
  • 2
    I would drop this abomination immediately and switch to python if I could, but my job requires fortran. What I am doing is creating a checkpoint file for a computation. I am utterly shocked that a language that is 50 years old still does not have even the most basic things in the standard library. – Stefano Borini Mar 03 '11 at 23:21
  • @Stefano Borini - From the number of fortran questions you've posted, one would expect you knew by now that Fortran doesn't have a standard library (thank gawd for that). – Rook Mar 04 '11 at 00:16
  • @Stefano Borini: If it's for a checkpoint file, another solution is to write out the necessary data directly to a new file every iteration instead of copying an existing file. – steabert Mar 04 '11 at 06:18
  • @Rook : the fact that I know doesn't mean that I'm not pissed every time I have to do a trivial operation and I have to reinvent the wheel, squared – Stefano Borini Mar 04 '11 at 09:36
  • @steabert: I can't do it. the restart requires knowledge of all the previous iterations as well, not only of the last one. – Stefano Borini Mar 04 '11 at 09:36
  • @Stefano Borini: If you write the data after each iteration in a new file, how can you not have all the information then? – steabert Mar 04 '11 at 09:52
  • @steabert : I would have to copy the information from the previous file into the new one, then start from the new one and continue adding data. That's why I need a copy operation. – Stefano Borini Mar 04 '11 at 10:02
  • 1
    @Stefano Borini: euhm, if you already have the info of the first iteration in a file, why would you need to copy it and then add new info instead of writing the new info directly to a new file??? If the first iteration, all data is written to files ITER1_blabla, then in the second switch to files ITER2_blabla, I fail to see how you cannot have all data there... – steabert Mar 04 '11 at 10:33
  • @steabert : because information does not copy magically from ITER1_file to ITER2_file. In addition, if I restart, I want to have all the data of the previous run saved. If the program crashes, I want to have at least one file which is guaranteed to be consistent. – Stefano Borini Mar 04 '11 at 11:48
  • @Stefano Borini: maybe I'm just thickheaded or plain stupid, but having information in 10 files or 1 file is the same to me. I'm not talking about copying info from ITER_1 to ITER_2, they both have info of their respective iteration. If your program fails in the middle of iteration 11, you have then 10 files combining all the necessary data. Well, that was the last of my comments :) – steabert Mar 05 '11 at 10:39
0

For Intel Fortran

subroutine copy_file (file_name, file_name_new)
! copies a file file_name to file_name_new
! file_name and file_name_new must include the path information and may include wildcard characters

USE ifport 
implicit character*100 (f)
character*1000 fnam
logical*4 logical_result

len1 = len_trim(file_name); len2 = len_trim(file_name_new)
fnam = 'copy/y ' //file_name(1:len1) //' '//file_name_new(1:len2)

l = len_trim(fnam)
logical_result = systemqq(fnam(1:l))

return
end
Austin Henley
  • 4,625
  • 13
  • 45
  • 80
Cedric
  • 1
0

The previous answer didn't work for me so I wrote the following subroutine

!=============================================================================================================================!
!                                                                                                                             !
!                           This subroutine copies file_name to file_name_new writing command to cmd                          !
!                                                                                                                             !
!=============================================================================================================================! 
 subroutine copy_file (file_name, file_name_new)
 use ifport 
 implicit none
!=============================================================================================================================
! D e c l a r a t i o n s
!=============================================================================================================================
 character(len=*),intent(IN) :: file_name_new,file_name
!----------------------------------------------------------------------------------------------------------------------------- 
 logical                     :: logical_result
!=============================================================================================================================
! S t a t e m e n t s
!============================================================================================================================= 

 logical_result = systemqq('copy "'//trim(file_name) //'" "'//trim(file_name_new)//'"')

!==============================================================================================================================
 end subroutine copy_file 
amelie
  • 11
  • 1
    I guess your file names have spaces in them for this fix to make sense. In any case `systemqq` is intel - specific. I'd recommend `execute_command_line` instead. – agentp Sep 15 '16 at 18:26
  • 1
    @agentp and copy is windows specific – Stefano Borini Sep 15 '16 at 22:58
  • well of course, the answer to the 5 year old question remains "no", there is not a standard built in system agnostic solution. At least now there *is* a standard way to issue a shell command. – agentp Sep 16 '16 at 02:05
  • And there will likely ever be. There is no such thing in C either, and that is a systems programming language, not Fortran. – Vladimir F Героям слава Sep 16 '16 at 21:06
0

! For Compaq/Intel Visual Fortran

subroutine copy_file(source_,dest_)   
use kernel32,only:CopyFile,FALSE 
implicit none  
integer ret  
character*(*), intent(in) :: source_, dest_  
ret = CopyFile(trim(source_)//""C, trim(dest_)//""C, FALSE)  
end subroutine copy_file
MathArt
  • 159
  • 7
0

Yes, Fortran has pathetic I/O and shouldn't be used for this sort of thing if at all possible. What a shame that some of us are forced to do it.

I just read the source file and simultaneously write to the destination, line-by-line. So far this works for me, but is very inefficient.

Dealing with files and portability is annoying with Fortran, and SYSTEM calls are often not very good either. The windows OS doesn't properly follow linux linked files, and Windows/Linux/MacOS have different separaters, I have been caught out with stack limits inherent in the SYSTEM call, and so on.

Good luck !