Joined: 06 Apr 2021 Posts: 123 Location: argentina
Can you tell me what functionality you use with rexx in your daily work?
Im now deciding if I read or not a book about rexx programing in z/os, I think that maybe if I know what type of useful functionalities the people working in mainframe with rexx use I will decide better if invert hours studying this language.
thank you, I searched in the forum but I did not find topics related to this I know create.
Can you tell me what functionality you use with rexx in your daily work?
Im now deciding if I read or not a book about rexx programing in z/os, I think that maybe if I know what type of useful functionalities the people working in mainframe with rexx use I will decide better if invert hours studying this language.
thank you, I searched in the forum but I did not find topics related to this I know create.
Joined: 06 Apr 2021 Posts: 123 Location: argentina
sergeyken wrote:
Ali_gezer wrote:
Can you tell me what functionality you use with rexx in your daily work?
Im now deciding if I read or not a book about rexx programing in z/os, I think that maybe if I know what type of useful functionalities the people working in mainframe with rexx use I will decide better if invert hours studying this language.
thank you, I searched in the forum but I did not find topics related to this I know create.
I want to know what kind of programs with rexx people can use in a daily basis.
In my work there are rexx programs that for example entering a copy name this program show you the copy without having to do it on your own.
Im talking about this kind of examples.
I want to know what kind of programs with rexx people can use in a daily basis.
In my work there are rexx programs that for example entering a copy name this program show you the copy without having to do it on your own.
Im talking about this kind of examples.
The questions is as senseless as: “Give me examples of everyday usage of COBOL/JCL/C/C++/PL1/Java/Python/etc,etc,etc”
I personally use REXX whenever I need a quick creation of a script for almost any type of automated processing of almost any type of data. Nothing specific, but any type of daily activities.
Joined: 06 Apr 2021 Posts: 123 Location: argentina
sergeyken wrote:
Ali_gezer wrote:
I want to know what kind of programs with rexx people can use in a daily basis.
In my work there are rexx programs that for example entering a copy name this program show you the copy without having to do it on your own.
Im talking about this kind of examples.
The questions is as senseless as: “Give me examples of everyday usage of COBOL/JCL/C/C++/PL1/Java/Python/etc,etc,etc”
I personally use REXX whenever I need a quick creation of a script for almost any type of automated processing of almost any type of data. Nothing specific, but any type of daily activities.
Sorry, I work with cobol and jcl since 2019 and in the 2 companies I have been working they only use rexx for particulars things, the main subjects that we use are cobol and jcl, so I thought that, perhaps wrongly, the other people of this forum were in the same situation.
I wanted to know functionalities that the people of the forum use with rexx to know if learn this language will help me in my work.
''I personally use REXX whenever I need a quick creation of a script for almost any type of automated processing of almost any type of data. Nothing specific, but any type of daily activities.''
can you describe me one of this script functions with a real example? I would be very happy with your experience.
This topic is an extraordinary example of full misunderstanding of Information Technology...
This is one of my recent examples. I had to split the members of multiple source libraries by the language of source code. Since there are about 250 libraries with 200-2000 members mixed in each of them, I decided to write two scripts, to be called from batch. This is not extremely excellent code, but I did it in a hurry, probably for one time use in my life.
Code:
/* REXX */ 00010000
ListLang: 00020000
00030000
Say "Enter ListLang" 00031000
00032000
DDLIST = 'LIBLIST' 00033000
DDPDS = '$PDSMEM' 00033100
DDLANG = 'LIBLANG' 00033200
"EXECIO 0 DISKR" DDLIST "(OPEN" 00034000
"EXECIO 0 DISKW" DDLANG "(OPEN" 00034100
If RC > 0 Then Exit 8 00035000
00035100
Do iPDS = 1 By 1 00035200
"EXECIO 1 DISKR" DDLIST 00035300
If RC = 2 Then Leave iPDS 00035400
If RC > 0 Then Exit 12 00035500
Parse Pull ListRecord " " . 00035605
Say " |" ListRecord "| " 00035704
Parse Upper Var ListRecord , 00035802
MemName RepCnt PDSDSN . 00035902
NewPDS = PDSDSN'('MemName')' 00036002
/* Say ">>>" NewPDS "<<<"*/ 00036106
"FREE FILE(" DDPDS ")" 00036202
"ALLOC FILE(" DDPDS ") DATASET('"NewPDS"') SHR" 00036302
If RC > 0 Then Iterate iPDS 00036402
00036502
GetLang = ScanLang( DDPDS ) 00036602
Push ListRecord Left( GetLang, 8 ) 00036702
"EXECIO 1 DISKW" DDLANG 00037002
End iPDS 00037102
"FREE FILE(" DDPDS ")" 00037202
00037302
"EXECIO 0 DISKR" DDLIST "(FINIS" 00037402
"EXECIO 0 DISKW" DDLANG "(FINIS" 00037502
Say "Exit ListLang." (iPds - 1) "members processed" 00037602
00037702
Return 0 00037802
/*====================================================================*/00037902
ScanLang: Procedure 00038002
Arg DDNAME . 00038102
/* 00038206
Say "Enter ScanLang" 00038302
*/ 00038406
"EXECIO 0 DISKR" DDNAME "(OPEN" 00038502
If RC > 0 Then Exit 8 00038602
00038702
Asm. = 0 00038802
Cobol. = 0 00038902
REXX. = 0 00039002
JCL. = 0 00039102
Asm.Keywords = "CSECT DSECT LTORG END ORG TITLE DS DC EJECT" , 00039202
"AMODE RMODE USING EQU" 00039302
REXX.Keywords = "REXX LEAVE ITERATE LEAVE SIGNAL ARG PARSE PULL QUEUE", 00039402
'EXPOSE SAY EXECIO "EXECIO' 00039502
00039602
Cobol.KeyWords = "DIVISION. SECTION. PROGRAM-ID. AUTHOR." , 00039702
"DATE-WRITTEN. DATE-COMPILED. INSTALLATION.", 00040002
"PERFORM GOBACK VARYING FILLER" , 00040302
"PIC PICTURE VALUE COMP COMP-1 COMP-3" , 00040402
"REDEF REDEFINES ZEROES BLANKS SPACES" , 00040502
"COMP. COMP-1. COMP-3." 00040602
JCL.KeyWords = "PROC JOB DD EXEC PEND" 00040702
JCL.KeyCode = "PROC= PGM= PARM= COND= NOTIFY=", 00040802
"DSN= DSNAME= DCB= VOL= SPACE=" 00040902
00041002
Do iLine = 1 By 1 00041102
"EXECIO 1 DISKR" DDNAME 00041202
If RC = 2 Then Leave iLine 00041302
Else If RC > 0 Then Exit 12 00041402
Parse Pull NewStatement =73 . 00041502
00041602
If Left( NewStatement, 1 ) = '*' Then 00041702
Asm.Comments = Asm.Comments + 1 00041802
Else If Substr( NewStatement, 7, 1 ) = '*' Then 00041902
Cobol.Comments = Cobol.Comments + 1 00042002
Else If Left( NewStatement, 3 ) = '//*' Then 00042102
JCL.Comments = JCL.Comments + 1 00042202
Else If Left( NewStatement, 2 ) = '//' Then 00042302
JCL.Code = JCL.Code + 1 00042402
00042502
If 0 = Verify( Left( NewStatement, 6 ), '0123456789' ) Then 00042602
Cobol.Numbers = Cobol.Numbers + 1 00042702
REXX.Comments = REXX.Comments + AnyCode( NewStatement, "/* */" ) 00042802
Asm.Keys = Asm.Keys + AnyWord( NewStatement, Asm.KeyWords ) 00042902
Cobol.Keys = Cobol.Keys + AnyWord( NewStatement, Cobol.KeyWords ) 00043001
REXX.Keys = REXX.Keys + AnyWord( NewStatement, REXX.KeyWords ) 00043201
If Left( NewStatement, 2 ) = '//' Then 00043401
JCL.Keys = JCL.Keys + AnyWord( NewStatement, JCL.KeyWords ) , 00043501
+ AnyCode( NewStatement, JCL.KeyCode ) 00043601
End iLine 00043701
"EXECIO 0 DISKR" DDNAME "(FINIS" 00043801
00043901
Asm.Total = Asm.Comments + Asm.Keys 00044001
/*Say "Asm.Total =" Asm.Total */ 00044106
Cobol.Total = Cobol.Comments + Cobol.Keys + Cobol.Numbers 00044201
/*Say "Cobol.Total =" Cobol.Total */ 00044306
REXX.Total = REXX.Comments + REXX.Keys 00044401
/*Say "REXX.Total =" REXX.Total */ 00044506
JCL.Total = JCL.Comments + JCL.Keys + JCL.Code 00044601
/*Say "JCL.Total =" JCL.Total */ 00044706
MaxTotal = Max( Asm.Total, Cobol.Total, REXX.Total, JCL.Total ) 00044801
/*Say "MaxTotal =" MaxTotal */ 00044906
00045001
If MaxTotal = 0 Then Lang = 'N/A' 00045101
Else If MaxTotal = Asm.Total Then Lang = 'ASM' 00045201
Else If MaxTotal = Cobol.Total Then Lang = 'COBOL' 00045301
Else If MaxTotal = REXX.Total Then Lang = 'REXX' 00045401
Else If MaxTotal = JCL.Total Then Lang = 'JCL' 00045501
/* 00045606
Say "Exit ScanLang:" Lang 00045701
*/ 00045806
Return Lang 00045901
/*====================================================================*/00046001
AnyWord: Procedure 00046101
Arg Text, WordList 00046201
Text = Translate(Text) 00047000
WordList = Translate(WordList) 00048000
00049000
#Words = Words(WordList) 00050000
Counter = 0 00050100
Do i = 1 To #Words 00050200
TWord = Word( WordList, i ) 00050301
Catch = (0 < WordPos( TWord, Text ) ) 00050401
Counter = Counter + Catch 00050801
End i 00051001
00051101
Return Counter 00051201
/*====================================================================*/00051301
AnyCode: Procedure 00051401
Arg Text, CodeList 00051501
Text = Translate(Text) 00051601
CodeList = Translate(CodeList) 00051701
00051801
#Words = Words(CodeList) 00051901
Counter = 0 00052001
Do i = 1 To #Words 00052101
TWord = Word( CodeList, i ) 00052201
Catch = (0 < Pos( TWord, Text ) ) 00052301
Counter = Counter + Catch 00052401
End i 00052501
00052601
Return Counter 00052701
/*====================================================================*/00053000
Code:
/* REXX */
ScanLang:
Say "Enter ScanLang"
DDNAME = 'SRCCODE'
"EXECIO 0 DISKR" DDNAME "(OPEN"
If RC > 0 Then Exit 8
Asm. = 0
Cobol. = 0
REXX. = 0
JCL. = 0
Asm.Keywords = "CSECT DSECT LTORG END ORG TITLE DS DC EJECT" ,
"AMODE RMODE USING EQU"
REXX.Keywords = "REXX LEAVE ITERATE BY TO RETURN EXIT PROCEDURE"
If MaxTotal = Asm.Total Then Lang = 'ASM'
Else If MaxTotal = Cobol.Total Then Lang = 'COBOL'
Else If MaxTotal = REXX.Total Then Lang = 'REXX'
Else If MaxTotal = JCL.Total Then Lang = 'JCL'
Say "Exit ScanLang:" Lang
Return Lang
/*====================================================================*/
AnyWord: Procedure
Arg Text, WordList
Text = Translate(Text)
WordList = Translate(WordList)
#Words = Words(WordList)
Counter = 0
Do i = 1 To #Words
Counter = Counter + (0 < WordPos( Word( WordList, i ), Text ) )
End i
Joined: 06 Jul 2010 Posts: 765 Location: Whitby, ON, Canada
REXX has interfaces to many execution environments, including TSO, ISPF, Db2, IMS, SDSF, CSL, Unix….and many others. It is easy to create applications that include all of these elements.
Joined: 01 Sep 2006 Posts: 2593 Location: Silicon Valley
I used to work for IBM. I wrote the rexx interface for the IMS Single Point of Control (IMS SPOC).
What rexx programmers appreciate is the ability to issue an IMS operator command from rexx, get and examine the command response, and based on that response to issue a subsequent operator command.
One example: query the queue count for an IMS transaction and if the queue was exceeding a threshold, then to start a new instance to help process the transaction queue.
And you can use the IMS SPOC rexx interface from Netview. Therefore, you can schedule and automate your IMS operations using your rexx programs. (yeah, there are probably other ways to automate, but I received kudos from our customers).
Joined: 01 Sep 2006 Posts: 2593 Location: Silicon Valley
Quote:
REXX has interfaces to many execution environments
Add to that list:
1. MVS operator commands. Like the IMS, you can examine the command response and automatically take a subsequent action.
2. RACF commands (I suppose this is a subset of TSO commands)
3. IPCS commands. For example, if your program abends and you capture a dump, from IPCS you can use rexx programs to find and format your unique control blocks to be more readable (or even system control blocks).
Joined: 01 Sep 2006 Posts: 2593 Location: Silicon Valley
Quote:
what type of useful functionalities the people working in
You are doing this backwards! It is you that has to decide what function you need to perform. After that, then you have figure out how to do it in rexx.
Joined: 01 Sep 2006 Posts: 2593 Location: Silicon Valley
You can call utility programs from rexx. For example, IEBGENER or IEBCOPY. Call the utility then immediately read its SYSPRINT file. Add logic to your rexx program to take further action based on the result of the utility program.
Joined: 06 Apr 2021 Posts: 123 Location: argentina
don.leahy wrote:
REXX has interfaces to many execution environments, including TSO, ISPF, Db2, IMS, SDSF, CSL, Unix….and many others. It is easy to create applications that include all of these elements.
can you give me some examples of rexx programs that use ispf in your work, or tso, only to get an idea of its daily use.
Joined: 06 Apr 2021 Posts: 123 Location: argentina
sergeyken wrote:
This topic is an extraordinary example of full misunderstanding of Information Technology...
This is one of my recent examples. I had to split the members of multiple source libraries by the language of source code. Since there are about 250 libraries with 200-2000 members mixed in each of them, I decided to write two scripts, to be called from batch. This is not extremely excellent code, but I did it in a hurry, probably for one time use in my life.
Code:
/* REXX */ 00010000
ListLang: 00020000
00030000
Say "Enter ListLang" 00031000
00032000
DDLIST = 'LIBLIST' 00033000
DDPDS = '$PDSMEM' 00033100
DDLANG = 'LIBLANG' 00033200
"EXECIO 0 DISKR" DDLIST "(OPEN" 00034000
"EXECIO 0 DISKW" DDLANG "(OPEN" 00034100
If RC > 0 Then Exit 8 00035000
00035100
Do iPDS = 1 By 1 00035200
"EXECIO 1 DISKR" DDLIST 00035300
If RC = 2 Then Leave iPDS 00035400
If RC > 0 Then Exit 12 00035500
Parse Pull ListRecord " " . 00035605
Say " |" ListRecord "| " 00035704
Parse Upper Var ListRecord , 00035802
MemName RepCnt PDSDSN . 00035902
NewPDS = PDSDSN'('MemName')' 00036002
/* Say ">>>" NewPDS "<<<"*/ 00036106
"FREE FILE(" DDPDS ")" 00036202
"ALLOC FILE(" DDPDS ") DATASET('"NewPDS"') SHR" 00036302
If RC > 0 Then Iterate iPDS 00036402
00036502
GetLang = ScanLang( DDPDS ) 00036602
Push ListRecord Left( GetLang, 8 ) 00036702
"EXECIO 1 DISKW" DDLANG 00037002
End iPDS 00037102
"FREE FILE(" DDPDS ")" 00037202
00037302
"EXECIO 0 DISKR" DDLIST "(FINIS" 00037402
"EXECIO 0 DISKW" DDLANG "(FINIS" 00037502
Say "Exit ListLang." (iPds - 1) "members processed" 00037602
00037702
Return 0 00037802
/*====================================================================*/00037902
ScanLang: Procedure 00038002
Arg DDNAME . 00038102
/* 00038206
Say "Enter ScanLang" 00038302
*/ 00038406
"EXECIO 0 DISKR" DDNAME "(OPEN" 00038502
If RC > 0 Then Exit 8 00038602
00038702
Asm. = 0 00038802
Cobol. = 0 00038902
REXX. = 0 00039002
JCL. = 0 00039102
Asm.Keywords = "CSECT DSECT LTORG END ORG TITLE DS DC EJECT" , 00039202
"AMODE RMODE USING EQU" 00039302
REXX.Keywords = "REXX LEAVE ITERATE LEAVE SIGNAL ARG PARSE PULL QUEUE", 00039402
'EXPOSE SAY EXECIO "EXECIO' 00039502
00039602
Cobol.KeyWords = "DIVISION. SECTION. PROGRAM-ID. AUTHOR." , 00039702
"DATE-WRITTEN. DATE-COMPILED. INSTALLATION.", 00040002
"PERFORM GOBACK VARYING FILLER" , 00040302
"PIC PICTURE VALUE COMP COMP-1 COMP-3" , 00040402
"REDEF REDEFINES ZEROES BLANKS SPACES" , 00040502
"COMP. COMP-1. COMP-3." 00040602
JCL.KeyWords = "PROC JOB DD EXEC PEND" 00040702
JCL.KeyCode = "PROC= PGM= PARM= COND= NOTIFY=", 00040802
"DSN= DSNAME= DCB= VOL= SPACE=" 00040902
00041002
Do iLine = 1 By 1 00041102
"EXECIO 1 DISKR" DDNAME 00041202
If RC = 2 Then Leave iLine 00041302
Else If RC > 0 Then Exit 12 00041402
Parse Pull NewStatement =73 . 00041502
00041602
If Left( NewStatement, 1 ) = '*' Then 00041702
Asm.Comments = Asm.Comments + 1 00041802
Else If Substr( NewStatement, 7, 1 ) = '*' Then 00041902
Cobol.Comments = Cobol.Comments + 1 00042002
Else If Left( NewStatement, 3 ) = '//*' Then 00042102
JCL.Comments = JCL.Comments + 1 00042202
Else If Left( NewStatement, 2 ) = '//' Then 00042302
JCL.Code = JCL.Code + 1 00042402
00042502
If 0 = Verify( Left( NewStatement, 6 ), '0123456789' ) Then 00042602
Cobol.Numbers = Cobol.Numbers + 1 00042702
REXX.Comments = REXX.Comments + AnyCode( NewStatement, "/* */" ) 00042802
Asm.Keys = Asm.Keys + AnyWord( NewStatement, Asm.KeyWords ) 00042902
Cobol.Keys = Cobol.Keys + AnyWord( NewStatement, Cobol.KeyWords ) 00043001
REXX.Keys = REXX.Keys + AnyWord( NewStatement, REXX.KeyWords ) 00043201
If Left( NewStatement, 2 ) = '//' Then 00043401
JCL.Keys = JCL.Keys + AnyWord( NewStatement, JCL.KeyWords ) , 00043501
+ AnyCode( NewStatement, JCL.KeyCode ) 00043601
End iLine 00043701
"EXECIO 0 DISKR" DDNAME "(FINIS" 00043801
00043901
Asm.Total = Asm.Comments + Asm.Keys 00044001
/*Say "Asm.Total =" Asm.Total */ 00044106
Cobol.Total = Cobol.Comments + Cobol.Keys + Cobol.Numbers 00044201
/*Say "Cobol.Total =" Cobol.Total */ 00044306
REXX.Total = REXX.Comments + REXX.Keys 00044401
/*Say "REXX.Total =" REXX.Total */ 00044506
JCL.Total = JCL.Comments + JCL.Keys + JCL.Code 00044601
/*Say "JCL.Total =" JCL.Total */ 00044706
MaxTotal = Max( Asm.Total, Cobol.Total, REXX.Total, JCL.Total ) 00044801
/*Say "MaxTotal =" MaxTotal */ 00044906
00045001
If MaxTotal = 0 Then Lang = 'N/A' 00045101
Else If MaxTotal = Asm.Total Then Lang = 'ASM' 00045201
Else If MaxTotal = Cobol.Total Then Lang = 'COBOL' 00045301
Else If MaxTotal = REXX.Total Then Lang = 'REXX' 00045401
Else If MaxTotal = JCL.Total Then Lang = 'JCL' 00045501
/* 00045606
Say "Exit ScanLang:" Lang 00045701
*/ 00045806
Return Lang 00045901
/*====================================================================*/00046001
AnyWord: Procedure 00046101
Arg Text, WordList 00046201
Text = Translate(Text) 00047000
WordList = Translate(WordList) 00048000
00049000
#Words = Words(WordList) 00050000
Counter = 0 00050100
Do i = 1 To #Words 00050200
TWord = Word( WordList, i ) 00050301
Catch = (0 < WordPos( TWord, Text ) ) 00050401
Counter = Counter + Catch 00050801
End i 00051001
00051101
Return Counter 00051201
/*====================================================================*/00051301
AnyCode: Procedure 00051401
Arg Text, CodeList 00051501
Text = Translate(Text) 00051601
CodeList = Translate(CodeList) 00051701
00051801
#Words = Words(CodeList) 00051901
Counter = 0 00052001
Do i = 1 To #Words 00052101
TWord = Word( CodeList, i ) 00052201
Catch = (0 < Pos( TWord, Text ) ) 00052301
Counter = Counter + Catch 00052401
End i 00052501
00052601
Return Counter 00052701
/*====================================================================*/00053000
Code:
/* REXX */
ScanLang:
Say "Enter ScanLang"
DDNAME = 'SRCCODE'
"EXECIO 0 DISKR" DDNAME "(OPEN"
If RC > 0 Then Exit 8
Asm. = 0
Cobol. = 0
REXX. = 0
JCL. = 0
Asm.Keywords = "CSECT DSECT LTORG END ORG TITLE DS DC EJECT" ,
"AMODE RMODE USING EQU"
REXX.Keywords = "REXX LEAVE ITERATE BY TO RETURN EXIT PROCEDURE"
If MaxTotal = Asm.Total Then Lang = 'ASM'
Else If MaxTotal = Cobol.Total Then Lang = 'COBOL'
Else If MaxTotal = REXX.Total Then Lang = 'REXX'
Else If MaxTotal = JCL.Total Then Lang = 'JCL'
Say "Exit ScanLang:" Lang
Return Lang
/*====================================================================*/
AnyWord: Procedure
Arg Text, WordList
Text = Translate(Text)
WordList = Translate(WordList)
#Words = Words(WordList)
Counter = 0
Do i = 1 To #Words
Counter = Counter + (0 < WordPos( Word( WordList, i ), Text ) )
End i
Thanks.
Well this is a good use of that language but I see that know rexx is a thing that will help in certain things, and I consider that knowing that language is a thing for experts.
Joined: 06 Apr 2021 Posts: 123 Location: argentina
Pedro wrote:
Quote:
what type of useful functionalities the people working in
You are doing this backwards! It is you that has to decide what function you need to perform. After that, then you have figure out how to do it in rexx.
in my work I solve all the things they gave me with cobol or jcl, I see that we only use rexx to by puting in the command line certain cobol program name it go directly to that program, same with copies. Other rexx program that I see here we have is to see know if one file is empty or have data or do not exist.
This are the two programs that I see in my work, so this is the reason I asked this to the people of this forum, to know another examples of programs that they saw o use.
Joined: 01 Sep 2006 Posts: 2593 Location: Silicon Valley
One of my favorite gee whiz programs was a rexx program that:
1. used the ISPF agent to automatically upload an HTML file from Windows to the mainframe.
2. automatically make some updates with new data to the HTML file
3. display updated HTML file for visual verification in ISPF editor, with HTML context sensitive color highlighting*.
4. download updated HTML file to Windows.
5. launch browser to display the updated HTML file.
* actually, I used the DTL highlighting at the time (HTML is a supported file type now).
Joined: 06 Jul 2010 Posts: 765 Location: Whitby, ON, Canada
Pedro wrote:
One of my favorite gee whiz programs was a rexx program that:
1. used the ISPF agent to automatically upload an HTML file from Windows to the mainframe.
2. automatically make some updates with new data to the HTML file
3. display updated HTML file for visual verification in ISPF editor, with HTML context sensitive color highlighting*.
4. download updated HTML file to Windows.
5. launch browser to display the updated HTML file.
* actually, I used the DTL highlighting at the time (HTML is a supported file type now).
You may know this already, but z/OS 2.5 kills the workstation agent. IBM’s stated reason is that it uses an unsecure connection. Rather than fix it, they opted to remove the feature from ISPF.
I had a number of cool apps that will stop working as soon as we “upgrade”.
Thanks.
Well this is a good use of that language but I see that know rexx is a thing that will help in certain things, and I consider that knowing that language is a thing for experts.
Joined: 01 Dec 2006 Posts: 792 Location: Pennsylvania
I had a request to take an input dataset and break it into several batches based on:
Code:
Header Client Batch# FTPDest
Data
Data
Data
Trailer
There could be one to several hundred of these batches.
I could have used Syncsort to break into batches however I would still have hundreds of datasets to FTP.
I chose to use Rexx to (very simplified description):
1) Find client name, Batch# and FTP destination from Header
2) Read all Data lines
3) When Trailer is found, write output to CLIENT.BATCH#.DATASET. Initiate FTP process to destination.