Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

File/Directory managment question

TommyCee
Beginner
4,064 Views

1) I'm well aware of the intrinsic inquire function which applies to a statement like:

inquire (file = "FileName.inp", exist=result)

But suppose I want to inquire about the existence of a Directory.  Is there a counterpart statement for this?  In some checking I've done, I haven't been able to find such.

2) Suppose we can find a way to determine the existence of some Directory.  If for a statement like the above result = .true., then suppose we want to purge (delete) it from an earlier run (so it can be created anew).  Is there a simple command to Remove this Directory?

In preliminary checking, I'm not sure I have seen a reliable command for this, especially one that isn't very dependent on the library one is using.  FWIW, in my case, I'm using DFlib (not iFort).

In DOS, I could always do this very easily.

0 Kudos
1 Solution
andrew_4619
Honored Contributor III
4,066 Views

I have to say (echoing FortranFan) that in my commercial applications which are windows based I would use windows sdk routines and standard Fortran only. Pumping out external commands such as I exampled I tend to use in 'for my own benefit only' quick bits of code as you can do a lot with very little code if you don't have all the potential pitfalls to secure against.  Sticking a command that can kill entire directory trees without warning is a bit of a worrying one if you have not been ultra careful in its use.

Anyway, TommyCee, I'm glad you found a result suitable for your needs and learned a couple of things which it the main objective and benefit of participating in forums such as this. I learn useful things here all the time....

 

View solution in original post

0 Kudos
27 Replies
Steven_L_Intel1
Employee
3,270 Views

GETFILEINFOQQ can tell you if a file is a directory (a flag in the PERMIT field of the structure returned.) There is no Intel Fortran library routine to delete a directory, but the Windows API routine RemoveDirectory will do it.

0 Kudos
TommyCee
Beginner
3,270 Views

I appreciate what you say, Steve, but I'd really like to just see if a directory is present (and if so, delete it).  As I say this, it now occurs to me that even if I can see if the directory exists, it may well be a problem deleting if it's filled w/ files.  Any thoughts on that?

0 Kudos
TommyCee
Beginner
3,270 Views

Using a command like this will definitely determine the existence of the Directory 'DIR':

INQUIRE (DIRECTORY='DIR', EXIST=LEXIST)

When 'DIR' is present, Lexist = .true.

The question now is:

If Lexist = .true., how best to wipe out 'DIR' ??

For Linux, I stumbled onto this gem:

rm -rf DIR

which supposedly will wipe out 'DIR' even it it's populated (w/ no prompts for each contained file).  A F90 command like this that will work within IVF would be great.

0 Kudos
Paul_Curtis
Valued Contributor I
3,270 Views

The Windows API provides a ready solution for path status,

[fortran]

handl = FindFirstFile (pathname, fdata)

netpath_ok = (handl /= INVALID_HANDLE_VALUE)

IF (netpath_ok) THEN

    nc = FindClose (handl)        ! release system resources

ELSE

[/fortran]
 

where pathname is a (null-terminated) path, ie pathname = c:\somedir\subdir//CHAR(0)

0 Kudos
TommyCee
Beginner
3,270 Views

Like I say - with

INQUIRE (DIRECTORY='DIR', EXIST=LEXIST)

I have a good way to verify if the "offending" directory is present.

I need to find an efficient way to KILL it (i.e., make it disappear) on the fly.

0 Kudos
andrew_4619
Honored Contributor III
3,270 Views

You can use DELDIRQQ or or the sdk function (http://msdn.microsoft.com/en-gb/library/windows/desktop/aa365488(v=vs.85).aspx) but niether work unless the dir is empty. You must delete the contents first.

0 Kudos
andrew_4619
Honored Contributor III
3,270 Views

A quick way would be to issue a command such as :

RD /S /Q "C:\Users\UserName\Desktop\Folder"

which deletes "folder" and all it contents without and prompts assuming you have permission and there are no locked files etc...

 

0 Kudos
TommyCee
Beginner
3,270 Views

OK app4619 - I appreciate your comments and here are mine:

DelDirQQ is a nonstarter if the "offending" directory is populated w/ files.

The other link SDK link leads to C++ routines which, while ideally suited to the task at hand, do not marry well w/ F90.  (I didn't want to have to build a DLL.)

And your RD /S /Q "C:\Users\UserName\Desktop\Folder" appears to be a DOS command which is not (at least easily) executable in the F90 framework.

The most fruitful option was the one Steve put me onto w/ GetFileInfoQQ, which led me to a few other associated IFport functions.  The only way to do this, and it's what I like to call a "sledge hammer" approach" is to change directories TO the offending directory, and then delete the files.  In my case, if I am able to delete only 2 files, the main problem goes away b/c the other files will be overwritten by my code.

This first conjures the function ChangeDirQQ(TargetPath) - I'm using my own argument names.  Since this code needs to be generic/robust, the pathway to the offending directory must be created within the context of the (any) user's machine.  This conjures an associated function GetDriveDirQQ(WorkingDirPath).  So here, once I get the Working Directory Path, I concatenate the other part of the path that involves a couple subdirectories and - voila - I finally get the full pathway to the "offending" directory.  Success.

At this point, I need only one thing.  Rather than a weapon to kill a directory, I need an F90 weapon to kill an existing (and of course unopened) file.

Any ideas on how to kill a sitting file on the fly?

 

 

 

 

 

0 Kudos
FortranFan
Honored Contributor III
3,270 Views

TommyCee wrote:

.. I need an F90 weapon to kill an existing (and of course unopened) file.

..

Why unopened?

 

0 Kudos
TommyCee
Beginner
3,270 Views

Because it was (or may well have been) created in an earlier run of the program.  It's just sitting there.

As sure as I didn't mention this, someone would have cone in with a complicated suggestion & code to close it or unattach it, etc.

0 Kudos
andrew_4619
Honored Contributor III
3,270 Views
The dos command is simple one liner e.g. below. You will need to build the string to send to the system command if you want it to be more general

   USE IFPORT
   INTEGER(4) I
​   I = SYSTEM('RD /S /Q "C:\Users\UserName\Desktop\Folder"')

 

The "C command" in the sdk can be called direct from Fortran with a simple interface that is provided by "USE IFWIN".but as a pointed out and as you are aware it must be empty for that to work.

FortranFan
Honored Contributor III
3,270 Views

TommyCee wrote:

Because it was (or may well have been) created in an earlier run of the program.  It's just sitting there.

As sure as I didn't mention this, someone would have cone in with a complicated suggestion & code to close it or unattach it, etc.

Well, you said, "I need an F90 weapon to kill an existing file" and I was wondering why you couldn't do something as follows:

    ...
    INTEGER :: Lun
    CHARACTER(LEN=:), ALLOCATABLE :: SomeFileName
    CHARACTER(LEN=2048) :: IO_ErrMsg  !.. Arbitrarily long string
    LOGICAL :: FileExists
    INTEGER :: IO_Err
    ...
    !.. Specify the file name from whatever source you've 
    SomeFileName = ...
    ...
    INQUIRE (FILE=SomeFileName, EXIST=FileExists, IOSTAT=IO_Err, IOMSG=IO_ErrMsg)
    IF (IO_Err == 0) THEN
       IF (FileExists) THEN
          OPEN (NEWUNIT=Lun, FILE=SomeFileName, ACTION='READWRITE', IOSTAT=IO_Err, IOMSG=IO_ErrMsg)
          IF (IO_Err == 0) THEN
             CLOSE(UNIT=Lun, STATUS='DELETE', IOSTAT=IO_Err, IOMSG=IO_ErrMsg)
             IF (IO_Err /= 0)
                !.. Do the needful; error description for delete failure in IO_ErrMsg string
                ...
             END IF
          ELSE
             !.. Do the needful; error description for file open failure in IO_ErrMsg string
             ...
          END IF
       END IF
    ELSE
       !.. Do the needful; error description for file inquire failure in IO_ErrMsg string
       ...
    END IF

All you would be doing with the above is open the file and if open is successful, then immediately close it with a 'DELETE' status.

Any specific reason why something as simple as this wouldn't work for you?

 

0 Kudos
TommyCee
Beginner
3,270 Views

Thanks for your clarification, app4619.  As always, a little bit of code to give context is always a HUGE advantage.  I learned something about executing a "DOS" command in within F90 code.  I may well play w/ this to gain some familiarity.

To obviate the "directory must be empty" constraint, I have devised an algorithm to simply (or maybe not so simply) go to the target directory where I may delete the files of interest.

So, I need a command to delete a named file.  Using your template, would something like this work?

USE IFPORT
INTEGER(4) I
I = SYSTEM('del FileName')

Or, I wonder if I might use something like this which includes the entire path and not have to Change Directories:

USE IFPORT
INTEGER(4) I
I = SYSTEM('del FullPath\FileName')

 

 

0 Kudos
andrew_4619
Honored Contributor III
3,270 Views

RD (RMDIR) does not require the directory to be empty with /S so the command shown above should do what you want.

Remember with invoking dos commands that you need a 'silent' mode. I.e. if the command asks 'are you sure?' that is a problem so you need a silent command option (if it exists) rm and del have /Q (Quiet mode).

 

0 Kudos
TommyCee
Beginner
3,270 Views

At long last, I think I'm ready to wrap up this thread.  Thanks a lot for recent contributions by FortranFan & app4619.

In looking at the code FF presented, it looks like that would work but, if I may say so, involves 2 or 3 sledge hammers. <grin> But I appreciate it all the same ,,,

app4619's DOS command wrapped within a function  call to SYSTEM turns out to be the perfect ticket!  I had no idea I wielded such power at my fingertips all along ... <bigger grin>

I = SYSTEM('RD /S /Q "C:\Users\UserName\Desktop\Folder"')

will certainly do the trick, exactly as app4619 claimed. However, in my app, it's not robust in the sense that the pathway would have to be manually specified per machine [i.e., there is no (easy) way to "automatically" apply the results from GetDriveDirQQ(WorkingDirPath) ]

With this in mind, the ultimate robust way to do it is as I described in my earlier post, and then - once you're "looking" at the target directory - do this:

inquire (file = "OffendingFile.ext", exist=result)
if (result) I = SYSTEM('del "OffendingFile.ext"')

In preliminary testing I've done w/ this, it seems to work like a top!

My takeaway is that harnessing the SYSTEM function call, I have access to very powerful DOS commands.

All of a sudden, I'm feeling like the Midas Man.

0 Kudos
FortranFan
Honored Contributor III
3,270 Views

TommyCee wrote:

...

In looking at the code FF presented, it looks like that would work but, if I may say so, involves 2 or 3 sledge hammers. ...

...

My takeaway is that harnessing the SYSTEM function call, I have access to very powerful DOS commands.

All of a sudden, I'm feeling like the Midas Man.

Not sure where you see any sledgehammer, let alone several!

Do note the code I presented is standard Fortran, so you get all the benefits of using standard code, particularly portability, if that is important to you.

Do keep in mind the function SYSTEM (or SYSTEMQQ) is a non-standard extension that can be constraining depending on how and where your code will be used.  In addition, system calls such as this one need to be used with great caution.

0 Kudos
TommyCee
Beginner
3,270 Views

FF:

My only point was that my 2 lines of code does what your 20-odd lines of code does!

For coding, I apply the philosophy of Occam's Razor with the design goal:
simpler, smaller, lighter, fewer moving parts ===> results in the most robust application.

Your last point was most intriguing:

Do keep in mind the function SYSTEM (or SYSTEMQQ) is a non-standard extension that can be constraining depending on how and where your code will be used.  In addition, system calls such as this one need to be used with great caution.

I was unaware of this caveat and will bee on the lookout for errant behavior.  I appreciate the heads up, FF.

What I might really find useful (if there is such a thing) would be a short reference on tasks and their F90 syntax that can be accomplished using function SYSTEM.  I have searched MSDN and haven't really seen anything.  Maybe there's something elsewhere.

 

0 Kudos
FortranFan
Honored Contributor III
3,270 Views

TommyCee wrote:

..

My only point was that my 2 lines of code does what your 20-odd lines of code does!

...

Generally speaking, it isn't appropriate to compare number of lines of code unless it is prohibitively large in one scenario (which is not the case here).

Also, note most of the lines of code in my example are there to alert you to the fact that you need to consider navigating your program through a maze of potential error scenarios during any operations, particularly I/O and file processing.  So you'll need to account for the same with the SYSTEM function call as well, but the sample code shown didn't have any of that.  For example, what if the call fails or what if the file to be deleted is locked by some other process (so what happens to that other process if you were to brute-force the file delete step), etc.  Once you take such things into consideration, it will no longer be a couple of lines of code.  Alternately, if you were to ignore such things in the standard Fortran example, you can make do with a couple of lines too:

    IF (FileExists)  THEN
       OPEN (NEWUNIT=Lun, FILE=SomeFileName, ACTION='READWRITE')
       CLOSE (UNIT=Lun, STATUS='DELETE')
    END IF

But such an approach is not good programming practice, as you know.

TommyCee wrote:

..

What I might really find useful (if there is such a thing) would be a short reference on tasks and their F90 syntax that can be accomplished using function SYSTEM.  I have searched MSDN and haven't really seen anything.  Maybe there's something elsewhere.

...

SYSTEM function call is an Intel Fortran extension that is made available via IFPORT module.  This option is very powerful, as you've realized, and it can do almost everything that is possible via a system command - hence it needs to be used with great caution.  Look in Intel Fortran Help and Documentation for SYSTEM or SYSTEMQQ.

On the other hand, standard Fortran only allows a few systems programming options: Fortran 2003 and 2008 have added a few options that were not available previously such as getting command line arguments, environment variables, etc.  You can review the books mentioned in Dr Fortran's blog at https://software.intel.com/en-us/blogs/2013/12/30/doctor-fortran-in-its-a-modern-fortran-world for more details.

 

 

 

0 Kudos
TommyCee
Beginner
3,270 Views

FortranFan,

I appreciate all your caveats &  admonitions and don't want to engage in an argument w/ you on this forum.  I get your points.  In my world, monitoring code behavior is an ongoing process.  If extra lines of code (to create what I call Guardrails) become necessary, I will assuredly install them.  But there's also the adage "If it ain't broke, don't fix it."  What I have learned from this post I have incorporated into a subroutine.  Though you wouldn't know it because I have not cluttered this post w/ all my code, your concern what if the file to be deleted is locked by some other process would be highly unlikely since the file was closed by the previous execution of the program.  And as a practical matter, if (God forbid) the deletion failed to happen, it would not be the end of the world.  In my particular system, removal of 2 files was mainly an added a convenience to the user since in the execution of my program in another mode, they would not be overwritten.  To present more that I wanted to say, but to be more clear, if the program is run in one mode, 9 files would be written to several output directories.  If the program is immediately run in "the other mode", only 7 different versions (of the 9) of the same files would be written.  Hence, 7 of the 9 would be expected; 2 would be "left over" from the previous execution.  Hence, the need for my deletion subroutine, which so far does a marvelous job.

I appreciate the link to Dr.Fortran's bibliography.  I am familiar w/ some of the refs. he lists.

The closest thing I have found to what I seek is this:

https://software.intel.com/sites/products/documentation/hpc/composerxe/en-us/2011Update/fortran/lin/lref_for/source_files/rfsystm.htm

and its companion:

https://software.intel.com/sites/products/documentation/hpc/composerxe/en-us/2011Update/fortran/lin/lref_for/source_files/rfsystmq.htm#rfsystmq

Each of these links provides one tiny example showing actual syntax.  What I would like is a page that shows many different application examples for command line syntax.  That would be huge.

0 Kudos
FortranFan
Honored Contributor III
3,004 Views

No worries..

Since the files in question are related to your own program, whose details will be known within your code, and on which there will be Fortran-specific file I/O operations (at least WRITE statements) anyway, it does seem sticking with standard Fortran, instead of using a system command, is a cleaner approach.

0 Kudos
Reply