Detecting all file with same format and store the filename

Hi guys,

I would like to detect all files (number of files is unknown, but can be solved using “allocate”) with the same format, say .exe, inside of the same folder where the Fortran program is being run (so it’s easier, no need to set path) and store all of those filenames to be used further. Anyone know a solution to this?

Many thanks guys, you’re so supportive!

On Windows, you could do the following:

  • Run the command “dir /b *.exe” and redirect that to a suitable file
  • Read that file line by line.

The effect of the option /b is that only the names are printed.

On Linux you can do the same with “ls *.exe”.

Of course, you can alos use the system routines for this - opendir, readdir, closedir on Linux if my memory serves me and completely different routines on Windows, but the route I sketched is the simplest.

1 Like

Although I’m not completely sure it works for your case, for a OS-agnostic library, I believe it’s worth having a look at the excellent fortran-filesystem by @scivision.

1 Like

Following @Arjen’s idea something like this could get you started:

program main
implicit none
character(len=:), allocatable :: cmd, file_content
integer :: fsze, u
logical :: found

#ifdef __linux
    cmd = 'ls -1 *.exe > output.log'
#else
    cmd = 'dir /b *.exe > output.log'
#endif
call execute_command_line(cmd)

inquire(file='output.log',exist=found, size=fsze)
open( newunit = u , file='output.log', status = 'old' , access='stream', action="read"  )

allocate(character(fsze) :: file_content)
read(u) file_content

end program

Then you would need to split the file_content variable to get each file name as a single string. You could check out this repo GitHub - szaghi/StringiFor: Strings Fortran Manipulator with steroids.

1 Like

On linux you probably want to use the full path to ls (ie /usr/bin/ls). Some (probably most) Linux distro’s will replace ls with an alias that turns on color support. When you redirect to some file you get a lot of extraneous characters written along with the file names etc. Also you might want to add a -1 to write our the files in one column. I would use then
/usr/bin/ls -1 *.exe > output.log

1 Like

Nobody so far has mentioned the execute_command_line and get_command intrinsic subroutines. Both are in Fortran 2018.

1 Like

:thinking:

1 Like

Sorry @hkvzjal I missed that one.

2 Likes

Actually, this doesn’t happen, but I’m not sure why it doesn’t. My “ls” command in a terminal window displays executable files in red and directory files in blue, but when I redirect the output to a file, I just get regular characters, with no embedded color codes. I think the shell looks to see what its output is connected to, and if it is an interactive terminal, then it adds the color, and if it is a regular file, then it doesn’t. Anyone know for certain how this works?

That is a POSIX command, so, practically speaking, it will work on any modern flavor of unix not just linux. The other branch is specific to MS Windows. If you are trying to write portable code, you might change the preprocessor test accordingly.

Regarding the filename, something like output.log might be an existing file in the working directory, so this sequence would overwrite that file. I would suggest using a different file name, perhaps placing the file in the /tmp directory, and then explicitly deleting it at the end.

1 Like

I think I was getting this on a CENTOS 6 system. However, I also think I used to get it on my Linux Mint (Ubuntu) systems as well. In my .bashrc file generated when I installed Mint I have the following line.

alias ls='ls --color=auto'

The point I was trying to make though is you should never do just an ls. Its always better with any Linux command you are running in execute_command_line to put the full path to the command in case (as in this example) its been aliased to something you might not want.

1 Like

Thanks all for being really helpful, i will try and if it’s success I will put it as the solution~

Many people recommend this as a security precaution with shell commands in shell scripts and in makefiles for the same reason. A local “ls” file might exist in the working directory which would then be executed by execute_command_line(), a shell script, or a makefile (at least when ./ is in the $PATH list). That file might have been placed there maliciously for the purpose of being executed at some later time. Changing the command to /bin/ls ensures that the expected unix command in being executed. In the case of “ls” in particular, I think that most shells, including bash, have a built-in version they use instead of /bin/ls, so that is one more aspect of uncertainty when using execute_command_line(). If the programmer keeps the command simple, and consistent with POSIX when possible, then the result is usually correct and portable.

1 Like

Wow, it’s all working guys. It’s hard to choose only one solution. I will choose @hkvzjal because he has put the code. Thank you all~

However, I found that if we use the command directly, for example:

call execute_command_line ("cmd/c dir /b *.exe> filenames.log")

it will now show CMD response back to screen, and if write that instruction to a .bat file and run it
for example:

open (gfnf,file="getfilenames.bat") 
write (gfnf,"(a34)") "cmd/c dir /b *.exe > filenames.log" 
call execute_command_line ("cmd/c dir /b *.inp > filenames.log")
close (gfnf,status="delete")

it will show the CMD response back to our Fortran screen. It’s pretty interesting! Hence, I would like to ask, is there any other file format besides .bat where we can also do the same?

Thanks again for your support

Edit: wait, i can’t choose a solution yet?