This article was inspired by a recent support call I received. It made me realise that many of you may not have noticed that IBM added a handy parameter to the RMVDIR (remove directory) command back in v6.1 called SUBTREE.
Let me set the scene and you can work out whether this is something that may be useful to you. If it is useful but something you think you already know about, be sure to skip down to my Pro Tip below on handling read-only objects before you abandon me.
RMVDIR fails with CPFA0AC – Directory contains objects
Imagine you have a need to delete a directory from the IFS but it is not empty and when you issue the RMVDIR command, you get error CPFA0AC – directory contains objects. Basically, this command (in its default form) only works if the directory is empty.
This is about as much use as the proverbial chocolate teapot. Can you imagine if IBM had done the same with libraries? You would not be able to issue a DLTLIB command unless you deleted the contents of it first.
In the example below, we have a directory called “Backup” in which we put copies of applications before upgrading them. Once the upgrade is complete, we want to remove them. In this case, there can often be thousands of objects in hundreds of subfolders.
The prospect of going through them all individually to delete them is about as appealing as a getting a haircut by Sweeney Todd.
If you wanted to automate this in a CL program, then it would become even trickier. But if we use the “Directory Subtree *ALL” parameter, then all this hassle goes away. In one simple command we can remove a directory including any objects and subfolders contained within it.
Pro Tip: Watch out for CPFA1C5 Object is Read Only.
Even if you’ve got *ALLOBJ, the RMVIR command still fails if any of the objects within it have the “read only” attribute set to yes. A sample of this error is shown in the screen shot below:
You can get round this using the CHGATR command. This allows you to remove the Read Only attributes for any and all objects contained in a folder or subfolder using (you guessed it) the Subtree *ALL parameter.
There is a sample of this in the screen shot below.
You can even script this method in a simple CL Program:
RMVDIR DIR('/backup') SUBTREE(*ALL) MONMSG CPF0000 CHGATR OBJ('/backup') ATR(*READONLY) VALUE(*NO) SUBTREE(*ALL) MONMSG CPF0000 RMVDIR DIR('/backup') SUBTREE(*ALL)
Now, for those of you who think I’ve gone potty or perhaps just made a mistake by leaving that first RMVDIR command there, bear with me. I know the RMVDIR is going to (or at least likely to) fail but this extra command can still save you time.
You see, the way the RMVDIR command works is that even if it can’t complete normally, it will remove all that it can, simply skipping the problem files and continuing until it has attempted to delete every candidate object.
If you let it run through and remove all it can, then when it comes to removing the READONLY attribute you have fewer files to process.
In the sample above, it was able to remove 134,498 of 134,671 objects with the first RMVDIR command. This means when I ran the CHGATR command (to remove the READONLY) it only had to process the 173 objects that had it set to yes, rather than the total number of objects which, in this case, was 134,671.
This can really save you loads of time as. Using this method, we only need to process the total number of objects once rather than twice.
If you are still running V5Rx
If you are still running v5, you do still have relatively easy options for manually deleting a directory that is not empty. I would suggest using the EDTF command or the IBM i Navigator Client.
I can’t quite remember when IBM added the function (but it was from at least V5R3). The EDTF command has a built-in file manager which includes a function to remove directories even if they are not empty. It is option 9, “Recursive Delete”, not, as you might expect, option 4 “Delete File”.
The example below is based on issuing the command EDTF ‘/backup*’. You will notice that this is an incomplete file or path name. You have to trigger the file manager view or else you will end up in file editor mode.
Once in the File Manger mode, you can then use option 9 to perform a recursive delete which will remove a directory including any objects or subfolders within it.
Pro Tip: There is also an option 6 here which will tell you how big that directory and all its contents are. This too can be very handy but watch out if there are lots of files; this function can take a long time to complete.
If you prefer the graphical method, then you can always launch the IBM i Access Navigator client and use the delete function in the File System section, see example below.
Neither of these options lets you script a delete in a CL Program. If you really need to do this and are still back running on v5 of IBM i, then my advice is to learn how to use the QSHELL or PASE command lines. In here, you can write a script that you can call from a CL program; you could then write a script to remove a directory like this.
Happy deleting, now you have no excuse for not tidying up your IFS and reclaiming some of your disk space.
Nice to see you…
Our next i-UG meeting will take place at Wyboston Lakes, UK, on September 9 and 10. We’ve already confirmed a number of excellent guest speakers including Paul Tuohy, Alison Butterill, David Spurway, Jyoti Dodhia, Therese Eaton, John Taylor, not to mention PowerWire superstars Andy Youens and Glenn Robinson. And, yes, I’ll be lurking around there too but please don’t let that put you off.
Hope to see you there, more details and registration available at the i-UG website.
Steve Bradshaw is the founder and managing director of Wolverhampton, UK-based Power Systems specialist Rowton IT Solutions and technical director of British IBM i user group i-UG. He has been a key contributor to PowerWire since 2012 and he also sits on the Common Europe Advisory Council (CEAC) which helps IBM shape the future of IBM i.