File exist check - Natural for Windows

To check whether a filename or folder name entered by a user exists or not, on a Windows environment, you may find this function useful.

It has a limit of 228 characters for the full path and name.
This limit could be removed by writing the “if exist” check to a batch file and then executing the batch file, but that approach needs one of the 1-32 work file numbers to be consistently available or passed as a parameter, which is messy. It is also slower, and we don’t need such long filenames at our site.


* Function  : FILEXIST(<work>)
*
* Action    : Returns TRUE if the work file or folder exists
*
* Parameter : Work file name  (A1-228)
*
* NB!         Max file name length is 228 characters, or NAT1308 results
*
DEFINE FUNCTION FILEXIST RETURNS (L)

DEFINE DATA
PARAMETER
1 #FILE             (A253) BY VALUE /* Allow >228 to trigger NAT1308 via EXAMINE REPLACE
LOCAL
1 #SHCMD            (A253) INIT <'CMD /C if exist ' - H'222522' - ' exit 1'>
END-DEFINE

EXAMINE #SHCMD FOR H'25' REPLACE FIRST #FILE
CALL 'SHCMD' #SHCMD 'NOSCREENIO' /* (SHCMD spares 11 more chars for #file than USR1052N)
IF RET('SHCMD') = 1
   FILEXIST := TRUE
ELSE
   FILEXIST := FALSE
END-IF

END-FUNCTION
END

Thank you, Anthony for your example.
What is the corresponding command in a Linux/Unix environment ?
(instead of cmd /c if exist…)

test -f ...

But to avoid OS-dependant code I would write a small subprogramm with an ON-ERROR-Routine that handles NAT1599…

I found that the DEBUG application causes problems once I have handled and discarded a work file error.

I can’t remember the deails now, but as far as I recall, it did something like forcing one to step through all subsequent code once the error had occurred.

Another reason I dropped the 1599 approach is that one can get a 1500 on an existing file, if you have no authority to access.

Is there a way to detect via Natural alone whether a read work’s 1500 is due to permissions versus a file which does not exist?

We found the difference important when reporting to the user to resolve, as they got confused if we said the file did not exist.

(I’ve often wondered why SAG, having platform-independent statements for work files, didn’t add a method to enquire on a file’s existence and accessibility. Would’t that logic already be in there somewhere…)

BTW I’ve upgraded FILEXIST if anyone wants it. The new version checks for path as well as file existence, and optionally creates the path.

The disadvantage is that it now does need to use a work file of its own to run the commands. SHCMD’s parameter is not long enough.

Another way when using Windows:


DEFINE DATA
   LOCAL
      1 #FILENAME (A60)
      1 OFSO HANDLE OF OBJECT  /* Handle to file system object
      1 #FILEEXISTS (L)
      1 #ERROR (I2)
END-DEFINE
*
CREATE OBJECT OFSO OF CLASS "SCRIPTING.FILESYSTEMOBJECT"
*
#FILENAME := 'C:\Temp\New Text Document.txt'
SEND "FILEEXISTS" TO OFSO WITH #FILENAME
  RETURN #FILEEXISTS GIVING #ERROR
IF #ERROR = 0
  IF #FILEEXISTS
    PRINT 'File' #FILENAME 'exists!
  ELSE
    PRINT 'File did not exist!!'
  END-IF
ELSE
  PRINT 'Error checking if file exists'
END-IF
OFSO := NULL-HANDLE
END

Via SHCMD (like Anthony Rose did) on Linux/Unix:

test -f      True if file exists and is a regular file.
test -r      True if file exists and is readable.
test -s      True if file exists and has a size greater than zero.
test -w      True if file exists and is writable.
...

On Windows: ???

I agree: OS-independent Natural-Code would be better.