Get file separator in Fortran
Asked Answered
A

4

5

Could you please tell me how to get the file separator of current operating system, for example \ in Windows and / in Unix, in Fortran at run-time.

Alidia answered 24/12, 2011 at 13:35 Comment(2)
"path separator of current OS"? What is that?Cleo
edited current OS - Operating system on witch the program runsAlidia
L
5

You can use Fortran 2003 Standard intrinsic procedure GET_ENVIRONMENT_VARIABLE to do something like this. Example:

CHARACTER(LEN=99999) :: path
CHARACTER(LEN=1)     :: path_separator
CALL GET_ENVIRONMENT_VARIABLE('PATH',path)
path_separator=path(1:1)
WRITE(*,*)'Path separator is ',path_separator
END

This program will output "/" as a path separator in UNIX or Linux. You could get this from other environment variables as well. Notice that this example is hardwired for UNIX/Linux. You would need a bit different logic to extract e.g. "\" for Windows, but I am not familiar with this system. I vaguely remember from Win95 having something like "c:\.....", so it is likely that in case of Windows you would look for "\" in path(3:3).

Hope this helps.

Latinity answered 24/12, 2011 at 17:20 Comment(6)
Do you need to read 99999 characters from the PATH environment variable in order to just extract the first character?Shy
@Shy +1 No. When I have to assume lengths (e.g. I have no idea what it looks like in Windows), I go for arbitrarily long. I believe length of 99 would be just fine.Latinity
@Shy Also, note that 99999 characters would not be actually read. Program would read whatever is the length of the path. The rest would just sit blank in memory.Latinity
From the Fortran standard and Fortran Wiki it seems that get_environment_variable reads as many characters as the length of path (your variable above) and is quite happy to truncate the environment variable to the length of path. So, on Unix at least, you could use call get_environment_variable('PATH', path_separator) to get /.Shy
Of course, deliberating over the length of one reasonably long character array is not something I should spend too much time worrying about!Shy
@Shy Yes I agree. The reason behind reading path into a long character string is because I am not sure whether in Windows, a '\' would come on position 3 or 103 or whatever. So, to be safe, I prefer to make sure I read the whole thing, and extract the desired substring. Thanks for the comments.Latinity
S
5

As far as I know the Fortran standard does not say anything about the file system path separator. The best I can suggest is to define a macro which defines the appropriate separator. For example

#if __unix__
character(len=1), parameter :: path_sep='/'
#elif _WIN32
character(len=1), parameter :: path_sep='\'
#else
#error "path_sep not defined. Set this constant for your system."
#endif

However, on Windows you can use either / or \ as your path separator (try it!) so on most systems there is no need to do anything special with the path separator.

Note that you don't need to determine the path separator at run-time. Since you must recompile your Fortran source for each new system you want to run it on, you just need to ensure that the correct path separator is specified at compile time for each new system (the path separator won't change between runs of your program on the same system).

Using preprocessor macros like those above it the obvious way of doing this: you can just add a new #elif clause for each new system you port your code to. This is alot easier than introducing picemeal solutions which check particular environment variables like the other answers suggest.

In addition the specifying the path separator you may also need to set parameters for other aspects of the operating system environment. For example, the current and parent directory characters (. and .. respectively under Windows and POSIX systems).

Finally, note that the preprocessor defines __unix__ and _WIN32 are widely used macros which indicate which system you are on and one, depending which system you are on, should be set by most compilers. If they are not set you can usually use the flag -D__unix__=1 or -D_WIN32=1 when you are compiling your source to set one of these macros. To preprocess your code using the -cpp (gfortran) or -fpp (ifort) command line options or change your source files extensions from .f to .F or from .f90 to .F90.

Shy answered 24/12, 2011 at 14:4 Comment(3)
I didn't succeed. I had error that this is illegal preprocessor directive. I use gfortran compilerAlidia
You have to preprosses the files. Either change your file extension from .f to .F or from .f90 to .F90. Alternatively, if you are using the intel compiler you can use the -fpp flag when compiling the file with these preprocessors.Shy
@Sergey Sorry, just noticed you said you are using gfortran. To invoke the preprocessor use the -cpp flag.Shy
L
5

You can use Fortran 2003 Standard intrinsic procedure GET_ENVIRONMENT_VARIABLE to do something like this. Example:

CHARACTER(LEN=99999) :: path
CHARACTER(LEN=1)     :: path_separator
CALL GET_ENVIRONMENT_VARIABLE('PATH',path)
path_separator=path(1:1)
WRITE(*,*)'Path separator is ',path_separator
END

This program will output "/" as a path separator in UNIX or Linux. You could get this from other environment variables as well. Notice that this example is hardwired for UNIX/Linux. You would need a bit different logic to extract e.g. "\" for Windows, but I am not familiar with this system. I vaguely remember from Win95 having something like "c:\.....", so it is likely that in case of Windows you would look for "\" in path(3:3).

Hope this helps.

Latinity answered 24/12, 2011 at 17:20 Comment(6)
Do you need to read 99999 characters from the PATH environment variable in order to just extract the first character?Shy
@Shy +1 No. When I have to assume lengths (e.g. I have no idea what it looks like in Windows), I go for arbitrarily long. I believe length of 99 would be just fine.Latinity
@Shy Also, note that 99999 characters would not be actually read. Program would read whatever is the length of the path. The rest would just sit blank in memory.Latinity
From the Fortran standard and Fortran Wiki it seems that get_environment_variable reads as many characters as the length of path (your variable above) and is quite happy to truncate the environment variable to the length of path. So, on Unix at least, you could use call get_environment_variable('PATH', path_separator) to get /.Shy
Of course, deliberating over the length of one reasonably long character array is not something I should spend too much time worrying about!Shy
@Shy Yes I agree. The reason behind reading path into a long character string is because I am not sure whether in Windows, a '\' would come on position 3 or 103 or whatever. So, to be safe, I prefer to make sure I read the whole thing, and extract the desired substring. Thanks for the comments.Latinity
P
1

Following IRO-bot suggestion, you could make a new environment variable, eg

export DELIMITER='/'

in unix

Now make a corresponding variable in windows, just with '\', and you are good to go.

If you don't want to set a global variable in windows, or doesn't have the rights to do so, put the following in an .bat file

set DELIMITER=\

For more on set, see http://www.ss64.com/nt/set.html You may have to run the fortran program from CMD when using set.

Finaly put the following in your fortran file

CHARACTER :: delimiter
CALL get_environment_variable('DELIMITER',delimiter)
Protestantism answered 29/12, 2011 at 16:29 Comment(0)
B
0

I rather favor the solution of 4 above, but with one modification:

function delimiter_detect() result(delim)
  character(LEN=1) :: delim
  character(LEN=258) :: path
  integer :: ii, stat_out
  call GET_ENVIRONMENT_VARIABLE('HOME',path,status=stat_out)
  if (stat_out/=0) go to 999
  ! xxx path='xx\' ! alternate test
  do ii=1, 258
     delim=path(ii:ii)
     if (delim=='/'.or.delim=='\') return
     ! ... Note: emacs does not recognize the second delimiter test
  enddo
999 continue
write(*,'(1x,a/1x,a/1x,a)') 'Could not obtain home directory path.', &
     'Restart program and manually insert path', &
     'to folder/directory containing input files.'
stop
end function delimiter_detect

That said, I haven't tested the concept on windows OS.

Beghard answered 4/10, 2015 at 3:50 Comment(1)
Could you please explain what this modification is? It isn't obvious to which answer you refer.Aquamarine

© 2022 - 2024 — McMap. All rights reserved.