Skip to content

Instantly share code, notes, and snippets.

@sriedmue79
Last active January 30, 2026 14:57
Show Gist options
  • Select an option

  • Save sriedmue79/66ce5df45405987e7a5e39d4b233f3e4 to your computer and use it in GitHub Desktop.

Select an option

Save sriedmue79/66ce5df45405987e7a5e39d4b233f3e4 to your computer and use it in GitHub Desktop.
IFS File Ownership Cleanup
--
-- Description: Can we use SQL to clean up old unused IFS files/directories based on the owner?
-- Warning: PLEASE READ :) Before executing the queries that utilize QSYS2.QCMDEXC() please carefully review the
-- generated RMVLNK commands and ensure that you truly want those files/directories to be deleted!
--First, let's retrieve a list of IFS streamfiles owned by user profile "JANDERSON"
--
--The QSYS2.OBJECT_OWNERSHIP() table function returns a list of objects owned by the user profile that is passed in.
-- This includes IFS files and directories, as well as QSYS objects like *PGM, *FILE, and *LIB objects etc. In the case
-- of QSYS objects the "PATH_NAME" field will be null. Since we only want IFS files, we specify WHERE PATH_NAME IS NOT NULL
SELECT PATH_NAME, OBJECT_TYPE
FROM TABLE ( QSYS2.OBJECT_OWNERSHIP(USER_PROFILE => 'JANDERSON') )
WHERE PATH_NAME IS NOT NULL;
--Next, let's see how to use IFS_OBJECT_STATISTICS to view details about one specific IFS file.
--
--The QSYS2.IFS_OBJECT_STATISTICS() table function can return various attributes of an IFS file/directory
-- including the creation timestamp, last accessed timestamp, size, etc. Those attributes are not returned
-- by the OBJECT_OWNERSHIP function, but we need them for this cleanup effort.
SELECT PATH_NAME, OBJECT_TYPE, CREATE_TIMESTAMP, ACCESS_TIMESTAMP, DATA_CHANGE_TIMESTAMP
FROM TABLE ( QSYS2.IFS_OBJECT_STATISTICS(
START_PATH_NAME => '/home/JANDERSON/very_important_file1.pdf',
SUBTREE_DIRECTORIES => 'NO') );
--Let's create an example RMVLNK command for deleting a single IFS streamfile.
--
--The CL command "RMVLNK" can be used to delete a file from the IFS. Here is an example of what such a command
-- might look like. Note that the value passed on the OBJLNK parameter must be enclosed in single quotes.
-- Since we are building this command in an SQL string, we have to "double up" the single quotes:
VALUES 'RMVLNK OBJLNK(''/home/JANDERSON/very_important_file1.pdf'')';
--We can execute that RMVLNK command using QSYS2.QCMDEXC(). This will delete a single IFS streamfile.
-- Using QSYS2.QCMDEXC() around the command string means the RMVLNK command will be executed on the server!
VALUES QSYS2.QCMDEXC('RMVLNK OBJLNK(''/home/JANDERSON/very_important_file1.pdf'')');
--Now let's start putting these steps together. We want to:
-- 1. Retrieve the list of IFS files owned by JANDERSON
-- 2. Also retrieve the relevant attributes about each file
--
--We can combine the OBJECT_OWNERSHIP() and IFS_OBJECT_STATISTICS() table functions to retrieve the list of files owned
-- by JANDERSON, plus the additional attributes about each of those streamfiles. We can select records based on the
-- "ACCESS_TIMESTAMP" which indicates the last time the file/directory was accessed.
--Note: If IFS_OBJECT_STATISTICS receives a directory as input, it will list all files within that directory.
-- This means the results could include files that are NOT owned by the user profile we are targeting!
-- To mitigate this, we include "WHERE PATH_NAME=OWNED_FILES.PATH_NAME" within the inner query.
WITH OWNED_FILES AS (
SELECT PATH_NAME, OBJECT_TYPE
FROM TABLE ( QSYS2.OBJECT_OWNERSHIP(USER_PROFILE => 'JANDERSON') ) )
SELECT 'RMVLNK OBJLNK(''' || OWNED_FILES.PATH_NAME || ''')' AS DLT_COMMAND,
OWNED_FILES.PATH_NAME,
PATH_ATTR.CREATE_TIMESTAMP,
PATH_ATTR.ACCESS_TIMESTAMP,
PATH_ATTR.DATA_CHANGE_TIMESTAMP
FROM OWNED_FILES, LATERAL (
SELECT CREATE_TIMESTAMP,
ACCESS_TIMESTAMP,
DATA_CHANGE_TIMESTAMP
FROM TABLE ( QSYS2.IFS_OBJECT_STATISTICS ( START_PATH_NAME => OWNED_FILES.PATH_NAME,
SUBTREE_DIRECTORIES => 'NO') )
WHERE PATH_NAME=OWNED_FILES.PATH_NAME ) AS PATH_ATTR
WHERE PATH_NAME IS NOT NULL
AND OWNED_FILES.OBJECT_TYPE = '*STMF'
AND PATH_ATTR.ACCESS_TIMESTAMP <= '2026-01-08'
ORDER BY PATH_ATTR.ACCESS_TIMESTAMP;
--For each of those files we can build the RMVLNK CL commands for deleting them. We build those RMVLNK
-- commands dynamically by concatenating the PATH_NAME into the OBJLNK() parameter.
WITH OWNED_FILES AS (
SELECT PATH_NAME, OBJECT_TYPE
FROM TABLE ( QSYS2.OBJECT_OWNERSHIP(USER_PROFILE => 'JANDERSON') ) )
SELECT 'RMVLNK OBJLNK(''' || OWNED_FILES.PATH_NAME || ''')' AS DLT_COMMAND,
OWNED_FILES.PATH_NAME,
PATH_ATTR.CREATE_TIMESTAMP,
PATH_ATTR.ACCESS_TIMESTAMP,
PATH_ATTR.DATA_CHANGE_TIMESTAMP
FROM OWNED_FILES, LATERAL (
SELECT CREATE_TIMESTAMP,
ACCESS_TIMESTAMP,
DATA_CHANGE_TIMESTAMP
FROM TABLE ( QSYS2.IFS_OBJECT_STATISTICS ( START_PATH_NAME => OWNED_FILES.PATH_NAME,
SUBTREE_DIRECTORIES => 'NO') )
WHERE PATH_NAME=OWNED_FILES.PATH_NAME ) AS PATH_ATTR
WHERE PATH_NAME IS NOT NULL
AND OWNED_FILES.OBJECT_TYPE = '*STMF'
AND PATH_ATTR.ACCESS_TIMESTAMP < '2026-01-08'
ORDER BY PATH_ATTR.ACCESS_TIMESTAMP;
--After verifying that the commands look ok, and that we truly want to delete those files, we can add
-- the QSYS2.QCMDEXC() function to actually execute those RMVLNK commands!
WITH OWNED_FILES AS (
SELECT PATH_NAME, OBJECT_TYPE
FROM TABLE ( QSYS2.OBJECT_OWNERSHIP(USER_PROFILE => 'JANDERSON') ) )
SELECT QSYS2.QCMDEXC('RMVLNK OBJLNK(''' || OWNED_FILES.PATH_NAME || ''')') AS DLT_COMMAND,
OWNED_FILES.PATH_NAME,
PATH_ATTR.CREATE_TIMESTAMP,
PATH_ATTR.ACCESS_TIMESTAMP,
PATH_ATTR.DATA_CHANGE_TIMESTAMP
FROM OWNED_FILES, LATERAL (
SELECT CREATE_TIMESTAMP,
ACCESS_TIMESTAMP,
DATA_CHANGE_TIMESTAMP
FROM TABLE ( QSYS2.IFS_OBJECT_STATISTICS ( START_PATH_NAME => OWNED_FILES.PATH_NAME,
SUBTREE_DIRECTORIES => 'NO') )
WHERE PATH_NAME=OWNED_FILES.PATH_NAME ) AS PATH_ATTR
WHERE PATH_NAME IS NOT NULL
AND OWNED_FILES.OBJECT_TYPE = '*STMF'
AND PATH_ATTR.ACCESS_TIMESTAMP < '2026-01-08'
ORDER BY PATH_ATTR.ACCESS_TIMESTAMP;
--Finally, we can confirm that the files are no longer listed under the user's ownership.
--
--Note: If the target user owned any directories, the deletion of one of those directories will fail if
-- there are still other files within the directory.
SELECT PATH_NAME, OBJECT_TYPE
FROM TABLE ( QSYS2.OBJECT_OWNERSHIP(USER_PROFILE => 'JANDERSON') )
WHERE PATH_NAME IS NOT NULL
AND OBJECT_TYPE = '*STMF';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment