How do I execute the rd command in Java? - java

How do I execute
rd /s /q c:\folder
in Java?
It woks perfectly on the command-line.

According to dtsazza's answer:
Runtime.getRuntime().exec("cmd.exe /k rd /s /q c:\\folder");
It works perfectly under WinXP SP3. The /k parameter shows, that a command will follow that has to be executed out of the cmd.exe.
Good luck with that!

Check the Runtime.exec method, which lets you call external processes. (Bear in mind that you lose some platform independence as this would rely on the machine having the rd command installed and on the path.)
A better option might be to do the same thing in pure Java - the following should be equivalent:
private void deleteDirectory(File directory)
{
for (File entity : directory.listFiles())
{
if (entity.isDirectory())
{
deleteDirectory(entity);
}
else
{
entity.delete();
}
}
directory.delete();
}
deleteDirectory(new File("C:\\folder"));
Adding error-checking as required. :-)

Check out FileUtils in Apache Commons-IO; in particular, the deleteDirectory and deleteQuietly methods, which can both recursively delete a directory.

Look at File.delete(String path) method, i.e.:
new File("c:\\folder").delete();
If the /s (recursive) deletion is important, then (untested):
public void deltree(File file) {
if (file.isDirectory()) {
for (File f : file.listFiles()) {
deltree(f);
}
}
file.delete();
}
public void deltree(String path) {
deltree(new File(path));
}
invoked as:
deltree("c:\\folder");

You only can delet empty directories in Java. First you have to delete the files and sub directories.
public static boolean removeDirectoryRecursively(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = removeDirectoryRecursively(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// The directory is now empty so delete it
return dir.delete();
}

If you want to execute it exactly the way you specified, you can do
Process p=Runtime.getRuntime().exec("cmd.exe /k rd /s /q c:\\folder");

Related

Check if File / Path is Alias, Shortcut or Symbolic link

I need to traverse files in a folder, and find all images. I need to include subdirectories, as well as made shortcuts (on windows), aliases (for mac users) or symbolic links.
I found working API that only works for the symbolic links.. I can't seem to determine if a file is an Alias or a shortcut..
Code I have:
private List<Path> getFiles(String folder) throws IOException {
List<Path> files = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(Paths.get(folder))) {
for (Path p : stream) {
System.out.println(p);
if(isLink(p.toFile())) {
files.addAll(getFiles(p.toFile().getCanonicalPath()));
}
String mimeType = Files.probeContentType(p);
if (StringUtils.isNotBlank(mimeType) && mimeType.contains("image")) {
files.add(p);
}
}
return files;
}
and
public static boolean isLink(File file) {
try {
if (!file.exists())
return true;
else {
String cnnpath = file.getCanonicalPath();
String abspath = file.getAbsolutePath();
return !abspath.equals(cnnpath);
}
} catch (IOException ex) {
System.err.println(ex);
return true;
}
}
Some help would be greatly appreciated!
Thanks!
To avoid toFile() calls you could also use Files.isSymbolicLink(Path p) and p.toRealPath() to determine the target of symbolic links for the paths you use.
Windows shortcuts are not modelled in Java File / Path APIs. An implementation which reads Windows shortcut binary format can be found here in another SO question - it better if using drive letters not using UNC pathnames.
I can't help for MacOS alias.
You should keep track of the directories visited in getFiles to avoid infinite loop when following links.

java.io.File #listFiles() Returns null from Windows cmd, but not as Eclipse Project Run

I have created this following method which I execute from a main thread
public static LinkedList<File> checkFile(String path, LinkedList<File> result) Throws IOException, SecurityException{
File root = new File(path);
File[] list = root.listFiles();
if (list == null)
return result;
for (File f : list) {
if (f.isDirectory()) {
checkFile(f.getAbsolutePath(), result);
} else {
result.add(f.getAbsoluteFile());
}
}
return result;
}
As long as it looks into the same location as the file itself, it can list all the files. But as soon as I point it to some other location (e.g. C:\somedir) it always returns null. When I run this inside eclipse, it is working fine. I don't assume that it's an issue with the classpath since I have added JAVA_HOME in windows path so it gets picked up (and the javac command also works fine).
I remember that there was a java bug in version 1.4 which was based around the error handling of listFiles method execution. But I am not sure why this is not working when I run it from command line using java command.
you can use the following wrapper to run it
public static void main(String[] args) throws IOException {
if (args.length == 0 || args[0] == null){
System.out.println("please specify path to the project's work folder");
return;
}
String folderPath = (String) args[0];
LinkedList<File> result = new LinkedList<>();
result = checkFile(folderPath, result);
long startTime = System.currentTimeMillis();
for (File file : result) {
System.out.println(file.getName());
}
}
EDIT
Okay, I have realised that I used a literal "path" instead of the parameter path and thanks for everyone who pointed this out. But the main problem prevails. The path is not recognised if it is not in the location as the executable class itself. When I try to run this from Eclipse, as a project, it works! But when I try to do it from command prompt using simple command, It doesn't work and #listFiles() always returns null.
java SomeExecItem -C:\myFolder\withclasses
From java.io.File#listFiles() method source analysis, What I understand is that if isInvalid() is evaluated as false when I run it from command line. The only possible reason is that the indexOf('\u0000') is evaluated as -1?
What is the difference here? Since I am not running in admin mode, I suppose Eclipse's view/read permission should be the same as a standalone command line application in cmd prompt?
Change File root = new File("path"); to File root = new File(path);. This will fix the problem.
You are not passing the parameter correctly. The try java SomeExecItem "C:\myFolder\withclasses" or java SomeExecItem C:\myFolder\withclasses.

list files inside of windows folder on cmd

I am trying to understand I/O in java. This is the code I have.
What I need to do is:
1) Should I write java list "C:\windows" on cmd and I need to see all the files inside of Windows.
2) I didn't understand File dir = new File(args[0]); What does this args[0] why we use it?
public class App {
public static void main(String []args)
{
try {
if (args.length != 1) {
System.err.println("Wrong usage");
System.exit(-1);
}
File dir = new File(args[0]);
if (!dir.isDirectory()) {
System.err.println("seems there is no directory ");
System.exit(-1);
}
File [] files = dir.listFiles();
System.setProperty("user.home", args[0]);
for (File file : files) {
if (file.isDirectory())
System.out.printf("%s<DIR>%n", file.getName());
else
System.out.printf("%s%n", file.getName());
}
}
catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
}
The answer you need is already in your question. After you compile the App.java will have a result call App.class, this is your class. To run it from the command you can use the java command line tool. It something like
java App C:/Windows
Where App is your application class without the .class. The C:/Windows is the parameter for your program, which is captured by the args[0].
First, you need to compile the java class
javac -g App.java
Then you can run it using:
java App "c:\\windows"

What is the most efficient way to list a directory?

So my title might not be the most descriptive but essentially I am doing this in one class:
Launching a perl script that creates a series of files
In another function within the same class, I would like to provision certain files that I have created from my first script into another script
//process 1
launchOnCommandLine("perl --arg1 -arg2");
What the above script does, is that it produces a bunch of files in the current working directory. In a second script what I want to be able to do is retrieve all the output files of extension (.example), retrieve their paths, concatenate them in a comma-seperated list, and feed it into a second script.
//process 2
launchSecondScript("perl --list-of-comma-seperated-file paths
What is the most efficient way to retrieve that comma-seperated string of file paths and provision it to a second function. I also know the directory where the files will be outputted so that is not a problem.
I might use a simple Java function to do this
private static String concatenateFilePaths(
String directory, String extension) {
StringBuilder sb = new StringBuilder();
File f = new File(directory);
if (f != null && f.isDirectory()) {
File[] files = f.listFiles();
for (File file : files) {
if (file != null
&& file.getName().endsWith(extension)) {
if (sb.length() > 0) {
sb.append(", ");
}
sb.append('"');
sb.append(file.getPath());
sb.append('"');
}
}
}
return sb.toString();
}
I then might use it like so
System.out.println(concatenateFilePaths("/tmp/test/",
".example"));
On my system ls /tmp/test
a.example b.example c
Result of above call
"/tmp/test/a.example", "/tmp/test/b.example"
Similar to Elliot's response here is a java7 (nio) version
public static String listFiles(String dir, String extensionToMatch){
StringBuilder fileList = new StringBuilder();
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(dir))) {
for (Path path : directoryStream) {
if(path.toString().endsWith(extensionToMatch)){
if(fileList.length() != 0){
fileList.append(",");
}
fileList.append(path.toString());
}
}
} catch (IOException ex) {}
return fileList.toString();
}

Delete Files with same Prefix String using Java

I have around 500 text files inside a directory with each with the same prefix in their filename, for example: dailyReport_.
The latter part of the file is the date of the file. (For example dailyReport_08262011.txt, dailyReport_08232011.txt)
I want to delete these files using a Java procedure. (I could go for a shell script and add it a job in the crontab but the application is meant to used by laymen).
I can delete a single file using something like this:
try{
File f=new File("dailyReport_08232011.txt");
f.delete();
}
catch(Exception e){
System.out.println(e);
}
but can I delete the files having a certain prefix? (e.g. dailyReport08 for the 8th month) I could easily do that in shell script by using rm -rf dailyReport08*.txt .
But File f=new File("dailyReport_08*.txt"); doesnt work in Java (as expected).
Now is anything similar possible in Java without running a loop that searches the directory for files?
Can I achieve this using some special characters similar to * used in shell script?
No, you can't. Java is rather low-level language -- comparing with shell-script -- so things like this must be done more explicetly. You should search for files with required mask with folder.listFiles(FilenameFilter), and iterate through returned array deleting each entry. Like this:
final File folder = ...
final File[] files = folder.listFiles( new FilenameFilter() {
#Override
public boolean accept( final File dir,
final String name ) {
return name.matches( "dailyReport_08.*\\.txt" );
}
} );
for ( final File file : files ) {
if ( !file.delete() ) {
System.err.println( "Can't remove " + file.getAbsolutePath() );
}
}
You can use a loop
for (File f : directory.listFiles()) {
if (f.getName().startsWith("dailyReport_")) {
f.delete();
}
}
Java 8 :
final File downloadDirectory = new File("directoryPath");
final File[] files = downloadDirectory.listFiles( (dir,name) -> name.matches("dailyReport_.*?" ));
Arrays.asList(files).stream().forEach(File::delete)
With Java 8:
public static boolean deleteFilesForPathByPrefix(final String path, final String prefix) {
boolean success = true;
try (DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(Paths.get(path), prefix + "*")) {
for (final Path newDirectoryStreamItem : newDirectoryStream) {
Files.delete(newDirectoryStreamItem);
}
} catch (final Exception e) {
success = false;
e.printStackTrace();
}
return success;
}
Simple version:
public static void deleteFilesForPathByPrefix(final Path path, final String prefix) {
try (DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(path, prefix + "*")) {
for (final Path newDirectoryStreamItem : newDirectoryStream) {
Files.delete(newDirectoryStreamItem);
}
} catch (final Exception e) { // empty
}
}
Modify the Path/String argument as needed. You can even convert between File and Path. Path is preferred for Java >= 8.
I know I'm late to the party. However, for future reference, I wanted to contribute a java 8 stream solution that doesn't involve a loop.
It may not be pretty. I welcome suggestions to make it look better. However, it does the job:
Files.list(deleteDirectory).filter(p -> p.toString().contains("dailyReport_08")).forEach((p) -> {
try {
Files.deleteIfExists(p);
} catch (Exception e) {
e.printStackTrace();
}
});
Alternatively, you can use Files.walk which will traverse the directory depth-first. That is, if the files are buried in different directories.
Use FileFilter like so:
File dir = new File(<path to dir>);
File[] toBeDeleted = dir.listFiles(new FileFilter() {
boolean accept(File pathname) {
return (pathname.getName().startsWith("dailyReport_08") && pathname.getName().endsWith(".txt"));
}
for (File f : toBeDeleted) {
f.delete();
}
There isn't a wildcard but you can implement a FilenameFilter and check the path with a startsWith("dailyReport_"). Then calling File.listFiles(filter) gives you an array of Files that you can loop through and call delete() on.
I agree with BegemoT.
However, just one optimization:
If you need a simple FilenameFilter, there is a class in the Google packages.
So, in this case you do not even have to create your own anonymous class.
import com.google.common.io.PatternFilenameFilter;
final File folder = ...
final File[] files = folder.listFiles(new PatternFilenameFilter("dailyReport_08.*\\.txt"));
// loop through the files
for ( final File file : files ) {
if ( !file.delete() ) {
System.err.println( "Can't remove " + file.getAbsolutePath() );
}
}
Enjoy !
You can't do it without a loop. But you can enhance this loop. First of all, ask you a question: "what's the problem with searching and removing in the loop?" If it's too slow for some reason, you can just run your loop in a separate thread, so that it will not affect your user interface.
Other advice - put your daily reports in a separate folder and then you will be able to remove this folder with all content.
or in scala
new java.io.File(<<pathStr>>).listFiles.filter(_.getName.endsWith(".txt")).foreach(_.delete())
Have a look at Apache FileUtils which offers many handy file manipulations.

Categories