You can use Qshell to list IFS files in a CL program on an IBM i system (this exact technique works on the older iSERIES and AS400 systems in the exact same way).
Here's a basic example of how you can achieve this:
- Create a CL program that uses Qshell to list the files in a specific directory.
- Redirect the output of the Qshell command to a file in the QTEMP library.
- Read the file in the CL program to process the list of files.
Here's a sample CL program:
DCLF FILE(QTEMP/FILELIST)
MONMSG MSGID(CPF0000)
/* Create a temporary file to store the list of files */
CRTPF FILE(QTEMP/FILELIST) RCDLEN(1000)
/* Use Qshell to list the files and redirect the output to the temporary file */
QSH CMD('ls /path/to/your/ifs/directory > /qsys.lib/qtemp.lib/filelist.file')
/* Read the file and process each entry */
OVRDBF FILE(FILELIST) TOFILE(QTEMP/FILELIST)
RCVF
DOLOOP: IF COND(&EOF *EQ '0') THEN(DO)
/* Process each file */
/* Your processing logic here */
RCVF
ENDDO
/* Clean up */
DLTOVR FILE(FILELIST)
DLTF FILE(QTEMP/FILELIST)
ENDPGM
In this example:
- The QSH CMD command lists the files in the specified IFS directory and redirects the output to a file in the QTEMP library.
- The RCVF command reads each record from the file, allowing you to process each file name as needed.
In this example:
Example IBM i CLLE Program
This code snippet will override the response from QSHELL (STDOUT) direct into a file in QTEMP so we can read it. It will position itself into the folder that is being read. Use QSHELL to list the files - the response will be sent to our file. Then we read the file and do whatever magic we want with the files:
CMD - READ_DIR
PARM KWD(DIR) TYPE(CHAR) LEN(255) EXPR(YES) PROMPT('IFS Folder Name ie: /home/bob')
PARM KWD(FILTER) TYPE(CHAR) LEN(30) DFT('.') EXPR(YES) PROMPT('Filter files (ie: *.CSV)')
CLLE - READ_DIR
/* Program : READ_DIR */
/* Author : nick litten */
/* Function: List selected files in an IFS DIR using QSHELL. */
/* Read that file and do some stuff with the files that are listed */
/* Compile Instructions.. 1: CRTPF FILE(QTEMP/READ_DIRF) RCDLEN(1000)*/ /* 2: CRTBNDCL PGM('library'/READ_DIR) */
/* SRCFILE('library'/QCLLESRC) */
/* SRCMBR(READ_DIR) */
/* REPLACE(*YES) */
PGM PARM(&DIR &FILTER)
COPYRIGHT TEXT('READ_DIR Ver.000')
DCLF FILE(READ_DIRF) OPNID(FILE)
DCL VAR(&DIR) TYPE(CHAR) LEN(255)
DCL VAR(&FILTER) TYPE(CHAR) LEN(30)
DCL VAR(&PREVPATH) TYPE(CHAR) LEN(1024)
DCL VAR(&PPATHLEN) TYPE(DEC) LEN(7 0)
DCL VAR(&QSHSTRING) TYPE(*CHAR) LEN(1024)
DCL VAR(&CNLSTS) TYPE(CHAR) LEN(1) VALUE('0')
DCL VAR(&CRASHED) TYPE(LGL) VALUE('0')
DCL VAR(&MSGID) TYPE(CHAR) LEN(7)
DCL VAR(&MSGDTA) TYPE(CHAR) LEN(256)
DCL VAR(&MSGFIL) TYPE(CHAR) LEN(10)
DCL VAR(&MSGFLIB) TYPE(CHAR) LEN(10)
DCL VAR(&MSGKEY) TYPE(CHAR) LEN(4)
DCL VAR(&RTNTYPE) TYPE(CHAR) LEN(2)
DCL VAR(&SENDER) TYPE(*CHAR) LEN(80)
MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(CRASH)) /* Global monitor to pick non monitored error conditions */
/* Validate the directory name */
CHKLNK OBJ(&DIR)
MONMSG MSGID(CPF0000) EXEC(DO)
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG)
MSGDTA(' Directory' *BCAT &DIR *TCAT ' not found')
TOPGMQ(PRV) MSGTYPE(ESCAPE)
ENDDO
/* collect the current directory we are pointed at - we will revert to this when we finish */
RTVCURDIR RTNDIR(&PREVPATH) DIRNAMLEN(&PPATHLEN)
CD DIR(&DIR)
MONMSG MSGID(CPFA09C) EXEC(DO)
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG)
MSGDTA('* Not authorised to directory' BCAT &DIR)
TOPGMQ(PRV) MSGTYPE(*ESCAPE)
ENDDO
/* create a work file to hold the list of files that we load from the IFS directory */
DLTF FILE(QTEMP/READ_DIRF)
MONMSG MSGID(CPF0000)
CRTPF FILE(QTEMP/READ_DIRF) RCDLEN(1000)
/* load the work file with a list of all the selected files in the IFS directory */
OVRDBF FILE(STDOUT) TOFILE(QTEMP/READ_DIRF) OVRSCOPE(JOB)
CHGVAR VAR(&QSHSTRING) VALUE('ls' *BCAT &DIR *TCAT '/' *TCAT &FILTER *TCAT ' -a | sort')
QSH CMD(&QSHSTRING)
DLTOVR FILE(STDOUT) LVL(*JOB)
IF COND(&PPATHLEN *GT 0) THEN(CD DIR(&PREVPATH))
OVRDBF FILE(READ_DIRF) TOFILE(QTEMP/READ_DIRF)
POSITION(START) OVRSCOPE(CALLLVL)
/* read the list of files from the IFS folder we listed */
DOWHILE COND(&CNLSTS = '0')
RCVF OPNID(FILE)
MONMSG MSGID(CPF0864) EXEC(LEAVE)
/* field &READ_DIRF is the file name ie: something.csv */
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG)
MSGDTA('-- Doing something with' *BCAT &FILE_READ_DIRF)
TOPGMQ(*PRV) MSGTYPE(*COMP)
/* Add your logic here to do the IFS FILE magic */
RTVJOBA ENDSTS(&CNLSTS)
ENDDO
DLTOVR FILE(READ_DIRF) LVL(*)
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Directory' *BCAT &DIR *TCAT ' has been read and files(' *TCAT &FILTER *TCAT ') have been processed') TOPGMQ(PRV) MSGTYPE(COMP)
RETURN
/* CRASH : Routine to handle unexpected errors */
CRASH:
IF COND(&CRASHED) THEN(RETURN)
CHGVAR VAR(&CRASHED) VALUE('1')
RCVMSG MSGTYPE(*LAST) MSGDTA(&MSGDTA) MSGID(&MSGID) RTNTYPE(&RTNTYPE) MSGF(&MSGFIL) SNDMSGFLIB(&MSGFLIB)
IF COND(&RTNTYPE *EQ '15' *OR &RTNTYPE *EQ '17') THEN(DO)
SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFIL) MSGDTA(&MSGDTA) MSGTYPE(*DIAG)
ENDDO
ESCAPE:
IF COND(&PPATHLEN *GT 0) THEN(DO)
CD DIR(&PREVPATH)
MONMSG MSGID(CPF0000)
ENDDO
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('* Program READ_DIR ended abnormally') MSGTYPE(*ESCAPE)
RETURN
ENDPGM: ENDPGM
I know I know.... That program just sort of grew as I put in my ear buds (not those poncy apple air pods) and got some programming grooove on.
When this runs it looks something like this:
Easy huh?