This morning I had an email from a blog subscriber ( Hi Rick! ) asking for a code tips on how to cleanup IFS file names to remove erroneous characters and/or malformed directory name slashes. Rather than reply with a plethora of programming options — here is an old, but functional, RPG code snippet that should help. 🙂
A looong time ago (in an office far far away) I faced a similar problem so decided to write a little RPGLE service program to give me some re-useable procedures to cleanup IFS file addresses.
In my case the users were asked to enter a file name in a green screen. What could go wrong? 😉
We all know that asking our users for a valid IFS File name is prone to spelling errors, syntax errors, finger slips and plain old end-user madness.
For example: Lets imagine an old IFS file that should be entered as /home/nick/myfile.cssv which is a lovely clean little file name.
In the real world, this could easily be entered as virtually any combination of keyboard whacks — /home\Nick//%¢&my file .CSV
While this file name might look reasonable to an end-user we (and when I say *we* I am referring to us propeller headed programming chaps and chappettes) know that the combination for front slashes, rear slashes and spaces in the file name might give us endless errors
So, I knocked up the #cleanifsfolder routine which basically switches everything to lower cases, removes duff characters, removes double spaces and replace spaces for underscores – obviously you can hack these rules to your heart’s delight.
Anyway, I’m waffling as usual, so lets just copy/paste the code:
// | // | #CleanIFSfolder - Clean up the string to remove Duff Stuff! | // | // | Remove duff characters from parm and then use a cheeky little do loop to // | squish it up so if this programs is passed a value of 'this is A file%¢&NaMe PlOp' // | // | The results will be calculated like this: // | starting 1. '/this is A file%¢&/NaMe PlOp' // | strip duff 2. '/this is A file /NaMe PlOp' // | lower 3. '/this is a file /name plop' // | SquishSingle 4. '/this is a file/name plop' // | dcl-proc #CleanIFSfolder export; dcl-pi #CleanIFSfolder char(1024); ParmIfsFolder char(1024) const; end-pi; dcl-s NeedsSquishing ind inz(*off); dcl-c @Dirty const('\,¢!~`?%&*<>()+"|:;'); // naughty characters edit this to your needs dcl-c @Clean const('/ '); dcl-s cleanIfsFolder char(1024); // Load up work field with the input value clear cleanIfsFolder; cleanIfsFolder = %subst(ParmIfsFolder:1:%Len(ParmIfsFolder)); If cleanIfsFolder <> *blanks; // Clean out any duff characters and switch to *blanks cleanIfsFolder = %Xlate(@Dirty:@Clean:cleanIfsFolder ); cleanIfsFolder = %Xlate(@quoteMark:@blank:cleanIfsFolder); // Make sure we only have forward slashes cleanIfsFolder = #LeanForward ( cleanIfsFolder ); // make it all lower case to be neat cleanIfsFolder = #lowercase ( cleanIfsFolder ); // Squish out any multiple blanks cleanIfsFolder = #SquishSingle ( cleanIfsFolder ); // Append '/' to the end cleanIfsFolder = %trim(cleanIfsFolder) + '/'; // underscore it to make it look saucy cleanIfsFolder = #underscoreIt ( cleanIfsFolder ); // change any accidental double forward-slashes to singles Dow %Scan('//': %trimR(cleanIfsFolder )) > *Zeros; NeedsSquishing = *on; cleanIfsFolder = %Replace('/':cleanIfsFolder:%Scan('//':%trimR(cleanIfsFolder )): 2); EndDo; // Squish out any blanks again after double thing if NeedsSquishing; cleanIfsFolder = #SquishSingle ( cleanIfsFolder ); Endif; Endif; Return cleanIfsFolder ; end-proc; // +----------------------------------------------------------------+ // | #LeanForward - Fix the Forward lash to backslash debacle | // +----------------------------------------------------------------+ dcl-proc #LeanForward export; dcl-pi #LeanForward char(1024); p_Data char(1024) const; end-pi; dcl-s $SlashData char(1024); $SlashData = %subst(p_Data:1:%Len(p_Data)); // Replace any LESS THAN or GREATER THAN Chevrons with UNDERSCORE $SlashData = %Xlate( '\':'/':$SlashData); Return $SlashData; end-proc; // +-----------------------------------------------------------+ // | #SQUISHSINGLE - Squish together leaving ONE single space | // +-----------------------------------------------------------+ dcl-proc #SquishSingle export; dcl-pi #SquishSingle char(1024); p_Data char(1024) const; end-pi; dcl-s $Squishey like(p_Data); // Load up work field with the input value $Squishey = %subst(p_Data:1:%Len(p_Data)); // replace all double blanks with a single one Dow %Scan(' ':%trimR($Squishey)) > *Zeros; $Squishey = %Replace(' ':$Squishey:%Scan(' ':%trimR($Squishey)):2); EndDo; $BigVariable = %trim($Squishey); Return $BigVariable; end-proc; // +-------------------------------------------------+ // | #UnderScoreIt - switch spaces to underscores | // | 1. 'this is a file name plop ' | // | 2. 'this_is_a_file_name_plop ' | // +-------------------------------------------------+ dcl-proc #UnderScoreIt export; dcl-pi #UnderScoreIt like($bigvariable); p_Data like($bigvariable) const; end-pi; dcl-s clnVariable like(p_Data); clnVariable = %subst(p_Data:1:%Len(p_Data)); clnVariable = %Xlate(@blank:@underScore:%trim(clnVariable)); // Replace Double UNDERSCORES with Singles Dow %Scan('__': %trimR(clnVariable )) > *Zeros; clnVariable = %Replace(@underScore:clnVariable:%Scan('__':%trimR(clnVariable)): 2); EndDo; // check for any left behind Dow %Scan('_ ':clnVariable ) > *Zeros; clnVariable = %Replace(' ':clnVariable:%Scan('_ ':clnVariable ): 2); EndDo; Return clnVariable; end-proc; // +---------------------------------------------------------+ // | #lowercase - purpose:convert text to lower case. | // | input:text data | // | Returns:lower case text data | // +---------------------------------------------------------+ dcl-proc #LowerCase export; dcl-pi #LowerCase like($bigvariable); ParmInput like($bigvariable) const; end-pi; dcl-s lowercaseWaffle like($bigvariable); EXEC SQL SET :lowercaseWaffle = lower(:ParmInput); Return lowercaseWaffle; end-proc; // +---------------------------------------------------------+ // | #uppercase - purpose:convert text to upper case. | // | input:text data | // | Returns:upper case text data | // +---------------------------------------------------------+ dcl-proc #UpperCase export; dcl-pi #UpperCase like($bigvariable); ParmInput like($bigvariable) const; end-pi; dcl-s upperCaseWaffle like($bigvariable); EXEC SQL SET :upperCaseWaffle = UPPER(:ParmInput); Return upperCaseWaffle; end-proc;
Be gentle with me….
These code snippets are from over a decade ago, I’m sure there are some super simple SQL way of doing this nowadays.
But hopefully they will be useful…
Hi Nick
I’ve just read a good article about clearing messy IFS files. Thank you for sharing your experience. I am right that utility you published there has nothing with reading IFS directory ( possibly containing the files with messing names ) but just cleans the file name specified as the parameter ?
Hi Nick
I’ve returned again to your code – it really nice not for those “old” time but for our modern time too… It seems me that you occasionally dropped the definition for “@quoteMark” variable mentioned in the beginning of your code. Can you please update it ? ( do you mean it was an single apostrophe value ? )