COBOL COBOL 2014 (ISO/IEC 1989:2014), built with GnuCOBOL 3.x ·
✓ verified by execution on 2026-08-16
Mainframes don’t have “files” and “folders” in the way modern operating systems do. Instead, they use a storage architecture based on datasets. If you are looking at JCL or trying to map files in a COBOL program, understanding this mainframe dataset vocabulary is absolutely mandatory.
The two most common dataset organizations you will encounter are Physical Sequential (PS) and Partitioned Datasets (PDS).
Physical Sequential (PS) Datasets
A Physical Sequential (PS) dataset is essentially a flat file. When a COBOL program writes to a PS dataset, the records are stored one after the other in the exact physical sequence they were written. To read the 10,000th record, the mainframe must read through the preceding 9,999 records.
Because of this sequential nature, PS datasets are perfect for massive batch processing tasks like reading a million transaction records, sorting them, and writing them out to a new PS dataset.
Partitioned Datasets (PDS) and Members
If every piece of source code on a mainframe were a separate PS dataset, management would be a nightmare. Enter the Partitioned Dataset (PDS).
A PDS is structurally similar to a modern directory or folder. It consists of a built-in directory structure and one or more members. Unlike a ZIP archive, you don’t need to “extract” a PDS to read its contents; the system can jump directly to the member you request.
When specifying a member within a JCL script or compiler directive, mainframe syntax uses parentheses. For example, if you have a PDS named MY.COBOL.SOURCE and a member named PAYROLL, you refer to it as MY.COBOL.SOURCE(PAYROLL).
The System Catalog
In the early days of computing, JCL writers had to explicitly specify which physical disk volume (e.g., VOL=SER=SYS001) contained a dataset.
Modern mainframes use the System Catalog. The catalog is basically a master directory that tracks the physical location of every dataset on the system. When a job requests MY.PROD.DATA, the operating system looks up the name in the catalog and automatically figures out which physical disk to spin up.
Mental Model Verification
Let’s test your understanding of how datasets and variables interact dynamically. In GnuCOBOL, we can map dataset names using environment variables.
What will the output of this snippet be?
Predict the outputcobol
Read the code. What exactly will it print? Commit to an answer before you look.
IDENTIFICATION DIVISION. PROGRAM-ID. DS-TEST. DATA DIVISION. WORKING-STORAGE SECTION. 01 PDS-NAME PIC X(15) VALUE "MY.COBOL.SOURCE". 01 MEMBER-NAME PIC X(05) VALUE "TEST1". 01 FULL-DSN PIC X(25). PROCEDURE DIVISION. STRING FUNCTION TRIM(PDS-NAME) "(" FUNCTION TRIM(MEMBER-NAME) ")" DELIMITED BY SIZE INTO FULL-DSN. DISPLAY FULL-DSN. STOP RUN.
Output
MY.COBOL.SOURCE(TEST1)
You predicted
This snippet correctly builds the DATASET.NAME(MEMBER) syntax dynamically using string manipulation, demonstrating how dynamic file assignments can point to specific PDS members at runtime.
Check yourself
What is a Partitioned Dataset (PDS) most analogous to in modern computing?
Reveal answer
A directory or folder containing individual files. — A PDS acts like a folder, containing a directory and multiple distinct 'members' which can be read directly.
How do you specify a specific member named MAINPROG inside a PDS named SYS1.COBOL.SOURCE?
Reveal answer
SYS1.COBOL.SOURCE(MAINPROG) — Mainframe syntax uses parentheses to denote a member within a PDS: DATASET.NAME(MEMBER).
What is the primary function of the mainframe system catalog?
Reveal answer
To map dataset names to the physical disk volumes where they reside. — The catalog keeps track of which volume contains which dataset, freeing the JCL writer from having to hardcode disk volume serial numbers.
Challenges
Challenge 1 +50 XP
Display the valid member syntax for member ABC inside PDS DATA.SET.NAME
cobol✓ solution verified at build time
COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the
fixed code should be, then open the solution and compare. The expected output
below is real — it came from compiling the solution with GnuCOBOL when this page
was built.
COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the
fixed code should be, then open the solution and compare. The expected output
below is real — it came from compiling the solution with GnuCOBOL when this page
was built.
A dataset holds 20-byte records, but this program's FD record is too short. The name survives; the job title is silently cut off. Fix the record description so the full role is read back.
This code runs. It just does the wrong thing. Read it, find the defect,
fix it — the tests below decide when you are right.
cobol✓ solution verified at build time
COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the
fixed code should be, then open the solution and compare. The expected output
below is real — it came from compiling the solution with GnuCOBOL when this page
was built.
Test 1 — expects "NAME: ALICE \nROLE: ENGINEER \n"
Need a hint? (−25% XP)
Count the bytes the record actually holds. EMP-REC has to be as wide as the data written to it.
Show solution (0 XP)
IDENTIFICATION DIVISION. PROGRAM-ID. LrecMismatch. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT EMP-FILE ASSIGN TO "emp.dat" ORGANIZATION IS LINE SEQUENTIAL. DATA DIVISION. FILE SECTION. FD EMP-FILE. 01 EMP-REC PIC X(20). WORKING-STORAGE SECTION. 01 WS-LINE PIC X(20) VALUE "ALICE ENGINEER ". 01 WS-IN PIC X(20). PROCEDURE DIVISION. OPEN OUTPUT EMP-FILE WRITE EMP-REC FROM WS-LINE CLOSE EMP-FILE OPEN INPUT EMP-FILE READ EMP-FILE INTO WS-IN CLOSE EMP-FILE DISPLAY "NAME: " WS-IN(1:10) DISPLAY "ROLE: " WS-IN(11:10) STOP RUN.