Wednesday, June 4, 2025

Simple way to check if a file exists in the IFS

Someone reached out to me asking for a straightforward way to check if a file exists in a particular folder in the IFS. They included their program, which, IMHO, was overly complicated. This will be another example of providing a simple, easy to understand, solution using SQL and RPG.

In my example I will be checking if a file exists, and the path for the file will be passed as a parameter from a RPG program. I also want to make the part that does the checking be a procedure. As one procedure can be called by multiple programs, as there could be other files in the future I want to check on.

I am going to create this procedure in a module that I will then bind into a RPG program. In the "real" world the procedure would be added to a service program, so that the logic within the procedure could be changed without having to recreate all the programs that use it.

My procedure called: Check_IFS_File, and it is in the module: TESTMOD0. There will be one parameter passed to the procedure, the IFS file's path name, and an indicator value will be returned to the calling program. If the indicator is on the file was found.

The procedure looks like:

01  **free
02  ctl-opt nomain ;

03  dcl-proc Check_IFS_File export reqproto(*no) ;
04    dcl-pi *n ind ;
05      inPathName varchar(100) const ;
06    end-pi ;

07    dcl-s Found ind ;

08    Found = *off ;

09    exec sql SELECT '1' INTO :Found
10               FROM TABLE(QSYS2.IFS_OBJECT_STATISTICS(
11                 START_PATH_NAME => :inPathName)) ;

12    return Found ;
13  end-proc ;

Line 3: I am using the REQPROTO(*NO) so I do not need to give a procedure prototype for this procedure.

Lines 4 – 6: This is the procedure interface. The procedure is passed the path name as a variable length character, and I have coded it as a constant. It returns an indicator value.

Line 7: This is the definition for an indicator variable I will be using to return a value to the calling program.

Line 8: Set the indicator variable to off, which means that the file was not found.

Lines 9 - 11: I am using the SQL table function IFS_OBJECT_STATISTICS to return a "1", which is the equivalent of on, to the indicator variable if the file is found.

Line 12: I return the value that is in the indicator variable to the calling program.

I would say that is a simple piece of RPG code.

I create the module, TESTMOD0, and then add it to my binding directory using the following command:

 ADDBNDDIRE BNDDIR(MYLIB/TESTBNDDIR) OBJ((TESTMOD0))

After adding a something to a binding directory I always like to check that it was added, and did not fail. I could use the WRKBNDDIRE command. But to show I can get to the same data another way I am going to use the BINDING_DIRECTORY_INFO SQL view:

01  SELECT ENTRY_LIBRARY,ENTRY,ENTRY_TYPE
02    FROM QSYS2.BINDING_DIRECTORY_INFO
03   WHERE BINDING_DIRECTORY_LIBRARY = 'MYLIB'
04     AND BINDING_DIRECTORY = 'TESTBNDDIR'

Line 1: I only want the library name, entry name, and the type of object it is.

Lines 3 and 4: I only want the results for the TESTBNDDIR binding directory in my library.

The results confirm that my module was added successfully to the binding directory.

ENTRY_LIBRARY   ENTRY        ENTRY_TYPE
-------------   ----------   ----------
*LIBL           TESTMOD0     *MODULE

And now to the RPG program that calls the procedure:

01   **free
02   ctl-opt main(Main) bnddir('TESTBNDDIR') ;

03   dcl-pr Check_IFS_File ind ;
04     *n varchar(100) const ;  // IFS path name
05   end-pr ;

06   dcl-proc Main ;
07     dcl-s Path varchar(100) ;
08     dcl-s Found ind ;

09     Path = '/home/MyFolder/file1.txt' ;
10     Found = Check_IFS_File(Path) ;
11     dsply ('1. Found = ' + Found) ;

12     Path = '/home/MyFolder/no_file.txt' ;
13     Found = Check_IFS_File(Path) ;
14     dsply ('2. Found = ' + Found) ;

15    Found = Check_IFS_File('/home/MyFolder/file1.txt') ;
16    dsply ('3. Found = ' + Found) ;

17    Found = Check_IFS_File('/home/MyFolder/') ;
18    dsply ('4. Found = ' + Found) ;           

18    return ;
19  end-proc ;

Line 2: I am using a Main procedure, which is something we should all be doing in 2025, and I am using the BNDDIR for the binding directory to use when creating this program.

Lines 3 – 5: The procedure prototype for the procedure I created above.

Line 9: I move the path name for the IFS I want to check exists to the Path variable.

Line 10: I call the procedure, passing to it the value in Path variable, and placing the returned indicator value into the variable Found.

Line 11: I am using the Display operation code, DSPLY, to show the value in the indicator variable.

Lines 12 – 14: These are basically the same as lines 9 – 11. This time the file in the path does not exist.

Lines 15 and 16: As I defined the path parameter in the procedure prototype as constant I can also pass the path name as a string too.

Lines 17 and 18: The path I am passing here is not for a file, this will see if the procedure can validate the existence of the folder.

When the program is created, and then called the following is displayed:

DSPLY  1. Found = 1
DSPLY  2. Found = 0
DSPLY  3. Found = 1
DSPLY  4. Found = 1

The first line shows that the file does exist in the folder.

Second line shows that the file, I knew did not exist, is not in the folder.

Third line shows I can use the string equally as well as the value in a variable.

Fourth line shows that the procedure can also be used to verify that a folder exists, regardless of whether it contains any objects.

I consider this another example of K.I.S.S., Keeping It Simple with SQL.

 

This article was written for IBM i 7.6, and should work for some earlier releases too.

No comments:

Post a Comment

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.