File Listing Order

Hi, I’m curious how Processing decides the order of files in a directory listing and if there is a way to sort alphabetical.

I’m using the sample code below and the listing doesn’t seem to be alphabetical or by date modified.

I need to loop through a few thousand images that are in subfolders, the subfolders are alphabetical and I want to keep my list that way.

Any ideas?

import java.util.Date;

void setup() {

  // Using just the path of this sketch to demonstrate,
  // but you can list any directory you like.
  String path = "/Users/philspitler/Desktop/";



  println("\nListing info about all files in a directory and all subdirectories: ");
ArrayList<File> allFiles = listFilesRecursive(path);
 


  for (File f : allFiles) {
   
    println("Full path: " + f.getAbsolutePath());
 
  }

  noLoop();
}

// Nothing is drawn in this program and the draw() doesn't loop because
// of the noLoop() in setup()
void draw() {
}




// Function to get a list of all files in a directory and all subdirectories
ArrayList<File> listFilesRecursive(String dir) {
  ArrayList<File> fileList = new ArrayList<File>(); 
  recurseDir(fileList, dir);
  return fileList;
}




// Recursive function to traverse subdirectories
void recurseDir(ArrayList<File> a, String dir) {
  File file = new File(dir);
  if (file.isDirectory()) {
    // If you want to include directories in the list
    a.add(file);  
    File[] subfiles = file.listFiles();
    for (int i = 0; i < subfiles.length; i++) {
      // Call this function on all files in this directory
      recurseDir(a, subfiles[i].getAbsolutePath());
    }
  } else {
    a.add(file);
  }
}
1 Like

Since Processing is based on Java, and you are pretty much using only Java functions everywhere, I looked for “Java change sort of File.listFiles();” and found that you can use Arrays.sort(subfiles); to sort array subfiles. However you would need to import java.util.Arrays to do the thing above - or you can use java.util.Arrays.sort(subfiles); instead.

So, this changes your recurseDir function to:

void recurseDir(ArrayList<File> a, String dir) {
  File file = new File(dir);
  if (file.isDirectory()) {
    // If you want to include directories in the list
    a.add(file);  
    File[] subfiles = file.listFiles();
    java.util.Arrays.sort(subfiles); //Sorts all files by name
    for (int i = 0; i < subfiles.length; i++) {
      // Call this function on all files in this directory
      recurseDir(a, subfiles[i].getAbsolutePath());
    }
  } else {
    a.add(file);
  }
}

I suggest looking for answers related to Java in the internet, as Processing is pretty much a wrapper for it and Java is more documented than Processing.

P.S. I also suggest using exit(); instead of noLoop(); to close the sketch as soon as it’s done.

1 Like

Wow, thanks for the quick reply, this seems to be exactly what I need.

Thanks.

Phil

a file type selector “*.img” might be also nice??

That could actually be useful, too. Here, the same function above, but with a file extension check added:

void recurseDir(ArrayList<File> a, String dir) {
  File file = new File(dir);
  if (file.isDirectory()) {
    // If you want to include directories in the list
    a.add(file);  
    File[] subfiles = file.listFiles();
    java.util.Arrays.sort(subfiles); //Sorts all files by name
    for (int i = 0; i < subfiles.length; i++) {
      // Call this function on all files in this directory
      recurseDir(a, subfiles[i].getAbsolutePath());
    }
  } else {
    String fileName = file.getName();
    if(
      //fileName.endsWith(".other-random-formats")||
      fileName.endsWith(".gif")||
      fileName.endsWith(".jpg")||
      fileName.endsWith(".jpeg")||
      fileName.endsWith(".tga")||
      fileName.endsWith(".png")
    ) {
      a.add(file);
    }
  }
}
1 Like

some rearrangement

// https://discourse.processing.org/t/file-listing-order/7148
// @philspitler  @Architector_4

ArrayList<File> myfiles;
String path = "/home/pi/projects/processing/sketchbook";
boolean piconly = true;

void setup() {
  println("\nListing info about all files in a directory and all subdirectories \n _filter_ piconly: "+piconly);
  myfiles = listFilesRecursive(path,piconly);
  for (File afile : myfiles)  println("File: "+afile );                       // afile.getAbsolutePath());
}

void draw() {
}

// Function to get a list of all files in a directory and all subdirectories // with piconly filter
ArrayList<File> listFilesRecursive(String dir,boolean piconly) {
  ArrayList<File> fileList = new ArrayList<File>(); 
  recurseDir(fileList, dir, piconly);                       // ( file array , root_directory , pictures only )
  return fileList;
}

// Recursive function to traverse subdirectories
void recurseDir(ArrayList<File> a, String dir, boolean piconly) {
  boolean showdirs = false;
  File file = new File(dir);
  if (file.isDirectory()) {
    if ( showdirs ) a.add(file);                                          // only if you want to include directories in the list
    File[] subfiles = file.listFiles();
    java.util.Arrays.sort(subfiles);     //Sorts all files by name
    for (int i = 0; i < subfiles.length; i++)   recurseDir(a, subfiles[i].getAbsolutePath(), piconly ); // Call this function on all files in this directory
  } else {
    String fileName = file.getName();
    if ( piconly ) {
    if ( //fileName.endsWith(".other-random-formats")||
      fileName.endsWith(".gif")   ||
      fileName.endsWith(".jpg")   ||
      fileName.endsWith(".jpeg")  ||
      fileName.endsWith(".tga")   ||
      fileName.endsWith(".png")   ||
      fileName.endsWith(".svg") 
      )      a.add(file);          // if picture for piconly
    } else { a.add(file); }        // all
  }
}


Why so picky?? :no_mouth:

listPaths():

Isn’t that for Python?
That function seems to exist in Java too, but what is the correct usage? Is it different from Python? It doesn’t seem to be documented anywhere, too.
Besides, does it return paths in alphabetical order?

It’s under Python Mode (Jython) forum category. :snake:

It’s a method belonging to Processing’s PApplet class: :coffee:

Processing.GitHub.io/processing-javadocs/everything/processing/core/PApplet.html#listPaths-java.lang.String-java.lang.String...-

It’s not that hard to convert it to Java Mode: :upside_down_face:

final String PICS_EXTS = "extensions=,png,jpg,jpeg,gif,tif,tiff,tga,bmp,wbmp";

final File dir = dataFile("");

String[] imagePaths = {};
int imagesFound = 0;

if (dir.isDirectory()) {
  imagePaths = listPaths(dir.getPath(), "files", "recursive", PICS_EXTS);
  imagesFound = imagePaths.length;
}

printArray(imagePaths);
println("Found", imagesFound, "image(s)");

exit();
PICS_EXTS = 'extensions=,png,jpg,jpeg,gif,tif,tiff,tga,bmp,wbmp'

dir = this.dataFile('')
imagePaths, imagesFound = (), 0

if dir.isDirectory():
    imagePaths = this.listPaths(dir.path, 'files', 'recursive', PICS_EXTS)
    imagesFound = len(imagePaths)

printArray(imagePaths)
print 'Found %d image(s)' % imagesFound

exit()

Given listPaths() returns an array of strings (String[]), it’s easily sortable by Arrays::sort(): :file_folder:

Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/util/Arrays.html#sort(java.lang.Object[])

1 Like

Hmm. I guess this then allows to change their listFilesRecursive() function to this:

final String PICS_EXTS = "extensions=,png,jpg,jpeg,gif,tif,tiff,tga,bmp,wbmp";


String[] listFilesRecursive(String dir) {
  String[] result = listPaths(dir, PICS_EXTS);
  sort(result);
  return result;
}

As stated, listPaths() returns a String[]. For File[], go w/ listFiles() instead:

Processing.GitHub.io/processing-javadocs/everything/processing/core/PApplet.html#listFiles-java.lang.String-java.lang.String...-

Those are all files extensions that loadImage() recognizes AFAIK.
We can trim it for a subset of it we actually need for a faster listing.

1 Like

Whoops! Fixed that one.

with this options we get our prior list again:

String[] myfiles = {};
final String PICS_EXTS = "extensions=,png,jpg,jpeg,gif,tif,tiff,tga,bmp,wbmp";
//final File dir = dataFile(""); // not work here on linux RASPBIAN  println(dir); shows: null/data
final File mydir = dataFile("/home/pi/projects/processing/sketchbook");

void setup() {
  
  println("check: "+mydir+" on files with "+PICS_EXTS);
  if ( mydir.isDirectory() )  myfiles = listPaths(mydir.getPath(), "recursive", "files", PICS_EXTS);
  printArray(myfiles);
}


1 Like

Hold on, why do we check if a directory .isDirectory() if we know that it’s directory? The only way mydir can be a directory is only if someone changes its value in the source code, and if they can do that they can deal with the error themselves!
This leaves us with no reason to define mydir as File and with dataFile(..., considering we only use it for mydir.getPath()
Then, why bother with making String[] myfiles?
I guess it makes sense to leave other Strings as variables to allow for easier change…
And, why bother putting a full path into dataPath(...)?
:hushed:

final String PICS_EXTS = "extensions=,png,jpg,jpeg,gif,tif,tiff,tga,bmp,wbmp";
final String mydir = dataPath(""); // kll, please run this only after settings() :v

void setup() {
  printArray(listPaths(mydir, "recursive", "files", PICS_EXTS));
}

Anyways, guys, the solution is found, why bother with needless improvements? :smiley:

1 Like

final File dir = dataFile("");

not work for me on RASPBIAN and WIN 7

(SOLVED) see File Listing Order

From the original forum question:

The if dir.isDirectory(): check block was intended to assure 1st whether the sketch’s “data/” folder already existed before proceeding any further. :flushed:

Although my current laptop is Win 8.1, my previous 1 was Win 7.

And I’m pretty sure both dataPath() & dataFile() work for all Windows versions!

Notice though that neither subfolders “data/” nor “code/” are created when a sketch project folder is 1st created.

Either we create them by ourselves or they’re created automatically when we drag & drop files into the PDE.

yes, made /data
copy in some pictures
tested on Raspberry Pi RASPBIAN and WIN 7
restarted Processing 3.4

Your sketch is buggy! You’re calling dataFile() before settings()! :bug:
The private system field PApplet::sketchPath is initialized just before settings() is called back btW. :calling:

Processing.GitHub.io/processing-javadocs/core/processing/core/PApplet.html#sketchPath--

1 Like