SSJX.CO.UK
Content

Processing files in a folder using the D Programming Language

Introduction

I wanted a way to run the contents of a folder through ffmpeg and turn some mp4 files into avi's my dvd player could play, after a bit of trial an error, below is what I ended up with! As it is made with D, there are no dependencies and it is fast and fairly memory safe. I did not use any one line cleverness so it is pretty easy to understand too!

Source

The code below has been extended to show how other file types could be added to the process.

import std.stdio;
import std.file;
import std.algorithm:endsWith;

import std.process;

void main(string[] args){	

	// Make sure we have a folder passed
	string fn;
	if (args.length>1){	
		fn=args[1];	
	}else{
		writeln("Processes a folder");
		writeln("Usage: ",args[0]," [folder]");
		return;
	}
	
	// Check to see if passed item exists and really is a folder!
	if (exists(fn)){
		if (fn.isDir==false){
			writeln("Error! Not a folder!");
			return;
		}
	}else{
		writeln("Cannot find this folder!");
		return;
	}
	
	foreach(string name; dirEntries(fn, SpanMode.shallow)){
		auto infile=name;
		string outfile=null;
		string[] runme;
		
		// Run the MP4 through FFMPEG (which is in my path)
		if (name.endsWith(".mp4")){
			outfile=name[0..$-4]~".avi";
			runme=["ffmpeg.exe","-i",infile,"-vtag","xvid","-q:v","5",outfile];
		}

		// Recompress a folder of JPEG files as JPEG XL using CJXL (which is also in my path)
		if (name.endsWith(".jpg")){	
			outfile=name[0..$-4]~".jxl";
			runme=["cjxl.exe",infile,outfile];
		}	
		
		// If our outfile name is still 'null' then we have not been able to process.
		if (outfile!=null){
			// Only convert if the destination file does not exist so we do not overwrite!
			if (exists(outfile)==false){
				writeln(infile~" => "~outfile);
				auto proc = execute(runme);
				if (proc.status != 0) writeln("Failed:\n", proc.output);
			}else{
				writeln(infile~" == Skipping! (Already processed?)");
			}
		}else{
			writeln(infile~" == Skipping! (Unknown file type)");	
		}
	}
}

Compile and run

Save the above and compile with your favourite D compiler, run specifying a folder to process. For example, if we saved the above as list.d, we would compile with dmd list.d and would get a file called list.exe. Using the above, to encode a folder using FFMPEG we would do the following:

>list test
test\witch_transform.mp4 => test\witch_transform.avi

And if we run it again:

>list c:\myfolder
test\witch_transform.avi == Skipping! (Unknown file type)
test\witch_transform.mp4 == Skipping! (Already processed?)

Modifying for other uses

The above can be easily modified for other tasks, for example to compress a folder of files as JPEG XL you could add the following:

// Recompress a folder of JPEG files as JPEG XL using CJXL (which is also in my path)
if (name.endsWith(".jpg")){	
	outfile=name[0..$-4]~".jxl";
	runme=["cjxl.exe",infile,outfile];
}	

Conclusion

Although many applications (such as IrfanView) have batch options, the above is useful if you need to be able to schedule an encode or if the utility you use does not allow the use of wildcards. Folder contents processing is the sort of task may be given to a scripting language like Python, using D instead would likely be much faster and mean less hardware resources are required which is both cheaper and better for the planet as detailed in this greener software guide.

Updated 15/12/2024
Created 12/12/2024