How to delete all empty folders and sub-folders and files in a specified directory

I want to be able to delete all empty folders and sub-folders and files in a specified directory.
I am testing some code and it doesn't work as expected.

In a different discussion, Leo mentioned this:

  • The Opus Delete command has a FAILNOTEMPTY argument which lets you tell it to delete something you think is empty while it will do nothing if it turns out that isn't the case. (Must be combined with NORECYCLE). From discussion: Trouble running rmempty.exe in script - #9 by JoeBeans

I wrote a test and it didn't go well.

function start(scriptCmdData) {

	if (scriptCmdData.func.args.got_arg.dir) {
		var arg = scriptCmdData.func.args.dir;
		var cmd = scriptCmdData.func.command;
		var folderEnum = DOpus.FSUtil.ReadDir(arg);

		DOpus.ClearOutput();

		cmd.ClearFiles();
		cmd.AddFiles(folderEnum.next(-1));
		cmd.Runcommand("Delete FAILNOTEMPTY NORECYCLE");
	} else {
		DOpus.Output("No directory was provided.");
	}
	DOpus.Output("DeleteEmpty Script is done.");
}

This does the opposite of what I want. It permanently deleted everything in the folder that wasn't empty and ignored the one item that was completely empty. And ofcouse I couldn't undo because of the "norecycle".

Not sure what to do. seems like I will need to also recursively search the sub folders.

That would add all files and folders to the list of things to be deleted. You probably don't want that, especially not the files.

The default script shows how to enumerate a directory and select just the folders under it.

Thanks, it took me a few minutest to find the "-1" trick, so I could pass all of the files and folders at once.

But, back to the question, why did it delete the non-empty files and folders but not the empty ones? It was my understanding that your original comment meant that FAILNOTEMPTY combined with NORECYCLE would prevent non-empty items from being deleted.

I wish I could find a way to check if something is empty, but I assumed that failnotempty was the way to go since that was what you replied with in the other discussion

I'm not sure what it will do with files, to be honest. But if you want it to work recursively then you're going to have to loop through the folders, and sub-folders, to find the empty ones in the script. And exclude the files. What you're doing currently doesn't make sense to achieve what you're trying to do.

Okay, can you please explain why it deleted a non-empty folder but didn't delete the empty folder? Also why do I need to use norecycle?

Please explain.

How do test for isEmpty? The only discussions I can find are many years old.

Why though? I want to delete empty files.

It's not that I want to do it recursivly, but it seems like that would be the only way. if you have a better way please tell me.

It shouldn't do that, AFAIK. Your script code is incomplete so I cannot try it here, unless you provide the full script (and also tell us how you are running it).

Also why do I need to use norecycle?

Because the documentation tells you FAILNOTEMPTY only works with NORECYCLE.

How do test for isEmpty? The only discussions I can find are many years old.

You already know how to get a list of what's in a directory. You can use that to check if a directory is empty.

Why though? I want to delete empty files.

As in zero-byte files? Then FAILNOTEMPTY won't help you as it's to help with cleaning up empty directories. But, in this case, you can probably do everything with a simple delete filter that matches anything which has size = 0 bytes, which will work with both files and folders. No scripting required in that case.

https://www.gpsoft.com.au/help/opus12/index.html#!Documents/Filtered_Operations.htm

This script is run by a button with this as the function/command DeleteEmpty DIR {sourcepath}
command

function OnInit(initData)
{
	initData.name = "DeleteEmpty";
	initData.version = "1.0";
	initData.copyright = "(c) 2023 chris";
//	initData.url = "https://resource.dopus.com/c/buttons-scripts/16";
	initData.desc = "";
	initData.default_enable = true;
	initData.min_version = "12.0";

	// Create a new ScriptCommand object and initialize it to add the command to Opus
	var cmd = initData.AddCommand();
	cmd.name = initData.name;
	cmd.method = "start";
	cmd.desc = initData.desc;
	cmd.label = "Delete Empty files and folders";
	cmd.template = "DIR/K,";
}

function start(scriptCmdData) {

	if (scriptCmdData.func.args.got_arg.dir) {//Check if parameter dir was passed an argument
		var arg = scriptCmdData.func.args.dir;
		var cmd = scriptCmdData.func.command;
		var folderEnum = DOpus.FSUtil.ReadDir(arg);

		DOpus.ClearOutput();
		DOpus.Output("Checking Path: " + arg + " for empty dir/files.");

		
		DOpus.Output(DOpus.TypeOf(folderEnum) );
		cmd.ClearFiles();
		cmd.AddFiles(folderEnum.next(-1));
		cmd.Runcommand("Delete FAILNOTEMPTY NORECYCLE");
		// while (!folderEnum.complete) {
		// 	var item = folderEnum.Next();
		// 	cmd.ClearFiles;
		// 	
		// 	// if (item.is_dir) {
		// 	// 	cmd.Runcommand("Delete FAILNOTEMPTY NORECYCLE");
		// 	// } else {
		// 	// 	
		// 	// }
		// }
	} else {
		DOpus.Output("No directory was provided.");
	}
	DOpus.Output("DeleteEmpty Script is done.");
}

I suggest using this: Remove Empty Directories (aka RED) (jonasjohn.de). It's been around for a while (so it's mature and presumably largely bug-free). I use it regularly (from a button in DO) and it works great.

(post deleted by author)

I just checked your link. I am using a different program that was posted by a user here on the forum. I will try yours.

I can't get the script to delete a non-empty folder.

The Delete FAILNOTEMPTY NORECYCLE command should fail as soon as it encounters a non-empty folder, after which it won't try to delete any further empty folders. So that probably explains why it didn't delete all your empty folders, if there was a non-empty one in the mix.

The purpose of FAILNOTEMPTY is to avoid accidents, where you think a folder is empty but it actually isn't. (For example, it was made for common "move everything up a level" buttons people made that often failed to consider nested directories with the same names as their parents, where moving everything up still left the original folder with things inside it that shouldn't be deleted.)

You could feed it a single folder at a time, and run the command more than once. You'd still need to make your script recursive in order to delete empty subdirectories. And you'd still need to make your script skip over files (or non-empty files, if that's what you want) as FAILNOTEMPTY is only about folders and doesn't change what the delete command does with files.

(Although I might change that, as it should probably skip all files entirely. The aim is to avoid accidents when "cleaning up" something that is expected to be an empty directory but isn't. Something being a file would be unexpected in that case, so the command should treat that as an error the same as it does a non-empty directory.)

Edit: There is also a SKIPNOTEMPTY which is similar but will skip non-empty folders instead of stopping entirely when it encounters one. But you'd still need to make your script recursive in order to do all the things you want.