How can I delete specified number of files from a file folder

Katalon Studio Version:
KSE 8.4.0, Build 208
Windows 10 Enterprise (64-bit)
Chrome Version 107.0.5304.122 (Official Build) (32-bit)

Hi folks,
My ‘DeleteAllTxtFiles()’ custom keyword works as expected and deletes all *.txt files in my Downloads folder. My question is how to make my ‘DeleteListOfTxtFiles()’ keyword only delete the specified number of files?

I use the following in the body of my test case to execute the keywords:

CustomKeywords.'tools.DeleteTextFiles.DeleteAllTxtFiles'()
//works as expected
CustomKeywords.'tools.DeleteTextFiles.DeleteListOfTxtFiles'()
//deletes *.txt all files in the folder
package tools
/** No imports required **/

public class DeleteTextFiles {
	//Deletes all text files
	def DeleteAllTxtFiles() {
		def filename = (System.getProperty('user.home') + '\\Downloads')
		new File(filename).eachFileMatch(~/.*.txt/) { file -> file.delete() }
        println("DeletedTextFile: " + filename)		
	}
	//Deletes 2 text files
	def DeleteListOfTxtFiles() {
		def filename = (System.getProperty('user.home') + '\\Downloads')
		for (def index : (0..2)) {
			new File(filename).eachFileMatch(~/.*.txt/) { file -> file.delete() }
			println("DeletedTextFile: " + filename)
		}
	}
}

I don’t think you can just delete “n” number of files, not if you are using wildcard characters. However, you could collect all the files that are in the folder into a list and then supply the Delete with a filename from the list until you have deleted the number you wanted. Just a few more steps added.

Another point if you don’t mind, you have a supposed “return” value of String but you don’t return any value. You can remove both the “String” from the declaration statement and the “return” statement from the routine. Or not.

Hi @grylion54,
The String and returns were mistakes on my part - thanks for noticing them.

Hi @grylion54,

I used this list to gather the files but am having an issue when trying to delete files.
Can you see where I am going wrong?

//imported files
import com.kazurayam.study20221030.PathComparableByFileLastModified
import com.kms.katalon.core.configuration.RunConfiguration
import internal.GlobalVariable as GlobalVariable
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.util.stream.Collectors
//Test case body
/**Reads in the path **/
Path dataDir = Paths.get(RunConfiguration.getProjectDir()).resolve("Data Files/testFiles")

List<String> folderFiles =
	Files.list(dataDir)
		.filter({ p -> p.toString().endsWith(".txt") })
		.map({ p -> new PathComparableByFileLastModified(p) })
		.sorted(Comparator.reverseOrder())
		.collect(Collectors.toList())

folderFiles.eachWithIndex  { p, index ->
	def fileName = (dataDir.relativize(p.get()))
    println("fileName: " + dataDir + '\\' + fileName)	
	
}
//When I disable delete the *.txt files are displayed in the console view as expected
new File(dataDir + '\\' + fileName).delete()

Result without trying to delete

2022-12-08 16:03:59.774 INFO  c.k.katalon.core.main.TestCaseExecutor   - --------------------
2022-12-08 16:03:59.779 INFO  c.k.katalon.core.main.TestCaseExecutor   - START Test Cases/A1_PreFeatureCases/01 How_to_cases/25 Katalon_tips/00 readFromFolder
2022-12-08 16:04:00.295 DEBUG testcase.00 readFromFolder               - 1: dataDir = get(getProjectDir()).resolve("Data Files/testFiles")
2022-12-08 16:04:00.314 DEBUG testcase.00 readFromFolder               - 2: folderFiles = reverseOrder()).collect(Collectors.toList())
2022-12-08 16:04:00.433 DEBUG testcase.00 readFromFolder               - 3: folderFiles.eachWithIndex({ java.lang.Object p, java.lang.Object index -> ... })
fileName: C:\Users\devers\Katalon_QAS_Projects\25-mfda-oap\Data Files\testFiles\EmailRecords.txt
fileName: C:\Users\devers\Katalon_QAS_Projects\25-mfda-oap\Data Files\testFiles\Readme.txt
2022-12-08 16:04:00.452 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/A1_PreFeatureCases/01 How_to_cases/25 Katalon_tips/00 readFromFolder

Result when trying to delete

2022-12-08 16:01:54.710 INFO  c.k.katalon.core.main.TestCaseExecutor   - --------------------
2022-12-08 16:01:54.714 INFO  c.k.katalon.core.main.TestCaseExecutor   - START Test Cases/A1_PreFeatureCases/01 How_to_cases/25 Katalon_tips/00 readFromFolder
2022-12-08 16:01:55.256 DEBUG testcase.00 readFromFolder               - 1: dataDir = get(getProjectDir()).resolve("Data Files/testFiles")
2022-12-08 16:01:55.275 DEBUG testcase.00 readFromFolder               - 2: folderFiles = reverseOrder()).collect(Collectors.toList())
2022-12-08 16:01:55.401 DEBUG testcase.00 readFromFolder               - 3: folderFiles.eachWithIndex({ java.lang.Object p, java.lang.Object index -> ... })
fileName: C:\Users\devers\Katalon_QAS_Projects\25-mfda-oap\Data Files\testFiles\EmailRecords.txt
fileName: C:\Users\devers\Katalon_QAS_Projects\25-mfda-oap\Data Files\testFiles\Readme.txt
2022-12-08 16:01:55.409 DEBUG testcase.00 readFromFolder               - 4: File(((dataDir + \) + fileName)).delete()
2022-12-08 16:01:55.420 ERROR c.k.katalon.core.main.TestCaseExecutor   - ❌ Test Cases/A1_PreFeatureCases/01 How_to_cases/25 Katalon_tips/00 readFromFolder FAILED.
Reason:
groovy.lang.MissingPropertyException: No such property: fileName for class: Script1670543550538
	at 00 readFromFolder.run(00 readFromFolder:24)
	at com.kms.katalon.core.main.ScriptEngine.run(ScriptEngine.java:194)
	at com.kms.katalon.core.main.ScriptEngine.runScriptAsRawText(ScriptEngine.java:119)
	at com.kms.katalon.core.main.TestCaseExecutor.runScript(TestCaseExecutor.java:445)
	at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:436)
	at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:415)
	at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:407)
	at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:284)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:142)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:133)
	at com.kms.katalon.core.main.TestCaseMain$runTestCase$0.call(Unknown Source)
	at TempTestCase1670544111871.run(TempTestCase1670544111871.groovy:25)

2022-12-08 16:01:55.432 ERROR c.k.katalon.core.main.TestCaseExecutor   - ❌ Test Cases/A1_PreFeatureCases/01 How_to_cases/25 Katalon_tips/00 readFromFolder FAILED.
Reason:
groovy.lang.MissingPropertyException: No such property: fileName for class: Script1670543550538
	at 00 readFromFolder.run(00 readFromFolder:24)
	at com.kms.katalon.core.main.ScriptEngine.run(ScriptEngine.java:194)
	at com.kms.katalon.core.main.ScriptEngine.runScriptAsRawText(ScriptEngine.java:119)
	at com.kms.katalon.core.main.TestCaseExecutor.runScript(TestCaseExecutor.java:445)
	at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:436)
	at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:415)
	at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:407)
	at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:284)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:142)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:133)
	at com.kms.katalon.core.main.TestCaseMain$runTestCase$0.call(Unknown Source)
	at TempTestCase1670544111871.run(TempTestCase1670544111871.groovy:25)

2022-12-08 16:01:55.444 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/A1_PreFeatureCases/01 How_to_cases/25 Katalon_tips/00 readFromFolder

It seems you have not defined “fileName” for some reason. Can you display a count of the “folderFiles” to see if it is not going into your definition of the “fileName”?

Hi @grylion54, thanks for the quick response.

I defined fileName in the “folderFiles.eachWithIndex” section.
Should that not work?

/**Reads in the path **/
Path dataDir = Paths.get(RunConfiguration.getProjectDir()).resolve("Data Files/testFiles")

List<String> folderFiles =
	Files.list(dataDir)
		.filter({ p -> p.toString().endsWith(".txt") })
		.map({ p -> new PathComparableByFileLastModified(p) })
		.sorted(Comparator.reverseOrder())
		.collect(Collectors.toList())

folderFiles.eachWithIndex  { p, index ->
	def fileName = (dataDir.relativize(p.get()))
    println("fileName: " + dataDir + '\\' + fileName)
	new File(dataDir + '\\' + fileName).delete()
	
}
//new File(dataDir + '\\' + fileName).delete()

When I try to delete from with the “folderFiles.eachWithIndex” section, I get this error.

2022-12-08 16:31:46.894 INFO  c.k.katalon.core.main.TestCaseExecutor   - --------------------
2022-12-08 16:31:46.898 INFO  c.k.katalon.core.main.TestCaseExecutor   - START Test Cases/A1_PreFeatureCases/01 How_to_cases/25 Katalon_tips/00 readFromFolder
2022-12-08 16:31:47.429 DEBUG testcase.00 readFromFolder               - 1: dataDir = get(getProjectDir()).resolve("Data Files/testFiles")
2022-12-08 16:31:47.449 DEBUG testcase.00 readFromFolder               - 2: folderFiles = reverseOrder()).collect(Collectors.toList())
2022-12-08 16:31:47.585 DEBUG testcase.00 readFromFolder               - 3: folderFiles.eachWithIndex({ java.lang.Object p, java.lang.Object index -> ... })
fileName: C:\Users\devers\Katalon_QAS_Projects\25-mfda-oap\Data Files\testFiles\EmailRecords.txt
2022-12-08 16:31:47.612 ERROR c.k.katalon.core.main.TestCaseExecutor   - ❌ Test Cases/A1_PreFeatureCases/01 How_to_cases/25 Katalon_tips/00 readFromFolder FAILED.
Reason:
groovy.lang.GroovyRuntimeException: Could not find matching constructor for: java.io.File(java.util.ArrayList)
	at Script1670543550538$_run_closure3.doCall(Script1670543550538.groovy:22)
	at 00 readFromFolder.run(00 readFromFolder:19)
	at com.kms.katalon.core.main.ScriptEngine.run(ScriptEngine.java:194)
	at com.kms.katalon.core.main.ScriptEngine.runScriptAsRawText(ScriptEngine.java:119)
	at com.kms.katalon.core.main.TestCaseExecutor.runScript(TestCaseExecutor.java:445)
	at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:436)
	at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:415)
	at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:407)
	at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:284)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:142)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:133)
	at com.kms.katalon.core.main.TestCaseMain$runTestCase$0.call(Unknown Source)
	at TempTestCase1670545903967.run(TempTestCase1670545903967.groovy:25)

2022-12-08 16:31:47.623 ERROR c.k.katalon.core.main.TestCaseExecutor   - ❌ Test Cases/A1_PreFeatureCases/01 How_to_cases/25 Katalon_tips/00 readFromFolder FAILED.
Reason:
groovy.lang.GroovyRuntimeException: Could not find matching constructor for: java.io.File(java.util.ArrayList)
	at Script1670543550538$_run_closure3.doCall(Script1670543550538.groovy:22)
	at 00 readFromFolder.run(00 readFromFolder:19)
	at com.kms.katalon.core.main.ScriptEngine.run(ScriptEngine.java:194)
	at com.kms.katalon.core.main.ScriptEngine.runScriptAsRawText(ScriptEngine.java:119)
	at com.kms.katalon.core.main.TestCaseExecutor.runScript(TestCaseExecutor.java:445)
	at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:436)
	at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:415)
	at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:407)
	at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:284)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:142)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:133)
	at com.kms.katalon.core.main.TestCaseMain$runTestCase$0.call(Unknown Source)
	at TempTestCase1670545903967.run(TempTestCase1670545903967.groovy:25)

2022-12-08 16:31:47.636 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/A1_PreFeatureCases/01 How_to_cases/25 Katalon_tips/00 readFromFolder

This looks an odd requirement, but you can make it.

Have a look at the following article.

5. Using NIO2 With Java 7

Java 7 introduced a whole new way of performing file operations using Files. It allows us to traverse a directory tree and use callbacks for actions to be performed.

You want to write a custom code implementing the “Visitor pattern”. The “Visitor” will increment the number of files that it deleted. The code will check the count and will skip deleting once the count reached to the criteria.

1 Like

I think the concern is to do with “scope”. What that means is that a definition of a variable is only good for a specific duration, such as a “for loop” like:

for (int cnt = 0; ...; cnt++) {
}

The variable “cnt” is only good from the for statement until the last curly bracket. If you try to get the value of “cnt” outside of the loop, it would be undefined.

In our case, the definition of fileName may be “scoped” to the definition of your eachWithIndex loop. To enlarge the scope, just identify the variable above the eachWithIndex, like:

List<String> folderFiles =
	Files.list(dataDir)
		.filter({ p -> p.toString().endsWith(".txt") })
		.map({ p -> new PathComparableByFileLastModified(p) })
		.sorted(Comparator.reverseOrder())
		.collect(Collectors.toList())

def fileName = ""

folderFiles.eachWithIndex  { p, index ->
	fileName = (dataDir.relativize(p.get()))
    println("fileName: " + dataDir + '\\' + fileName)
	new File(dataDir + '\\' + fileName).delete()
}

@Dave_Evers

You are careless about the type of variables.

You are not distiguishing java.lang.String and java.nio.file.Path.

The following line is warned:

	new File(dataDir + '\\' + fileName).delete()

by a message:

Could not find matching constructor for: java.io.File(java.util.ArrayList)

Do you see why? May be not. I will tell you.

You declared the variable dataDir to be an instance of java.nio.file.Path as you wrote:

        Path dataDir = Paths.get(....

And then you wrote

dataDir + '\\'

What are you doing here by an operator + ? The expression java.nio.file.Path + java.lang.String does not make sense in Java at all. If you write this in Java, you will get a compilation error.

However unfortunately Groovy language is too much tolerant about this kind of mistakes. Groovy won’t warn you of your mistake. Instead it seems that Groovy makes an instance of java.util.ArrayList out of dataDir + '\\'; and it terminated with an error “Could not find matching constructor for: java.io.File(java.util.ArrayList)”. This is just puzzling.

In short, your line

new File(dataDir + '\\' + fileName).delete()

is wrong. If I were you, I would try:

dataDir.resolve(fileName).toFile().delete()

@Dave_Evers

You should go back to reading some good Java book to learn the ABC of Java programming and learn how much you need to be careful about the data types.

In my humble opinion, Groovy is not a good language for beginner to learn the basics of programming; Groovy is designed to be less strict about data-types, which often confuses learners.

Thanks for your feedback and advice @kazurayam, much appreciated!

Cheers,
Dave

Thanks for your help @grylion54, much appreciated!