Q: I'm trying to use the following command, but I'm having trouble:
STRQSH CMD('find /path/to/files -name *.csv +
-exec /qsys.lib/mylib.lib/mypgm.pgm {} \;')
The CL program is receiving a null-terminated path name. The null character causes errors, and some of the characters after it look like "garbage." How do I handle this?
A: There are two ways to handle this.
The first way is to search for the null-terminator and make a copy of the filename without it. It's important that the result be placed in a new variable. You should never change a parameter that you received from QShell.
The following program demonstrates this technique:
PGM PARM(&PARM)
DCL VAR(&PARM) TYPE(*CHAR) LEN(1000)
DCL VAR(&FILE) TYPE(*CHAR) LEN(1000)
DCL VAR(&X00) TYPE(*CHAR) LEN(1) VALUE(X'00')
DCL VAR(&POS) TYPE(*DEC) LEN(4) VALUE(1)
/* FIND NULL-TERMINATOR */
LOOP: IF (%SST(&PARM &POS 1) *NE &X00) DO
CHGVAR VAR(&POS) VALUE(&POS + 1)
GOTO LOOP
ENDDO
/* MAKE A COPY WITHOUT THE NULL-TERMINATOR */
CHGVAR VAR(&POS) VALUE(&POS - 1)
CHGVAR VAR(&FILE) VALUE(%SST(&PARM 1 &POS))
/* RUN A COMMAND ON THIS FILENAME */
CPYFRMIMPF FROMSTMF(&FILE) TOFILE(YOURFILE)
ENDPGM
That program should work well with the FIND command that you sent me; However, it will not be as fast as it could be.
You see, for each file that QShell finds, it'll submit a new job to batch to run the CL program on that file and will then wait until that batch job ends. This requires a lot of extra work for the computer, so it takes longer.
A faster way is to have QShell write the files that it finds into a physical file and then read that physical file in your CL program to do the CPYFRMSTMF. The following program demonstrates doing it that way:
PGM
DCL VAR(&JOBNBR) TYPE(*CHAR) LEN(6)
DCL VAR(&LIB) TYPE(*CHAR) LEN(10) VALUE('MYLIB')
DCL VAR(&TEMPNAME) TYPE(*CHAR) LEN(10)
DCL VAR(&EOF) TYPE(*LGL) VALUE('0')
DCL VAR(&CMD) TYPE(*CHAR) LEN(200)
DCLF FILE(FILELIST)
/* CREATE A TEMPORARY FILE TO RECEIVE FILENAMES INTO */
/* NOTE: QSHELL CANNOT ACCESS QTEMP! */
RTVJOBA NBR(&JOBNBR)
CHGVAR VAR(&TEMPNAME) VALUE('TEMP' *CAT &JOBNBR)
DLTF FILE(&LIB/&TEMPNAME)
MONMSG CPF2105
CRTPF FILE(&LIB/&TEMPNAME) RCDLEN(1000) LVLCHK(*NO)
/* TELL QSHELL TO WRITE FILENAMES TO THE TEMP FILE */
/* Replace '/path/to/files' with the location of the files in */
/* your IFS! */
CHGVAR VAR(&CMD) VALUE('find /path/to/files -name *.csv > +
/qsys.lib/' *CAT &LIB *TCAT '.lib/' +
*CAT &TEMPNAME *TCAT '.file/' +
*CAT &TEMPNAME *TCAT '.mbr')
STRQSH CMD(&CMD)
/* READ FILENAMES FROM TEMP FILE */
OVRDBF FILE(FILELIST) TOFILE(&LIB/&TEMPNAME)
LOOP: RCVF
MONMSG MSGID(CPF0864) EXEC(CHGVAR &EOF VALUE('1'))
IF (&EOF *EQ '0') DO
CPYFRMIMPF FROMSTMF(&FILELIST) TOFILE(YOURFILE)
GOTO LOOP
ENDDO
DLTF FILE(&LIB/&TEMPNAME)
ENDPGM