// Cleaning Bash History using a Java 11 Single-File Sourcecode Program

Java 11 adds with JEP330 the ability to launch a Java source file directly from the command line without requiring to explicitly compile it. I can see this feature being convenient for some simple scripting or quick tests. Although Java isn't the most concise language it still has the benefit of being quite readable and having powerful utility APIs.

The following example reads the bash shell history from a file into a LinkedHashSet to retain ordering and keeps the most recently used line if duplicates exist, essentially cleaning up the history.


import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.LinkedHashSet;
import java.util.HashSet;
import java.util.stream.Stream;

public class HistoryCleaner {

    public static void main(String[] args) throws IOException {

        Path path = Path.of(System.getProperty("user.home")+"/.bash_history");

        HashSet<String> deduplicated = new LinkedHashSet<>(1024);
        try (Stream<String> lines = Files.lines(path)) {
            lines.forEach(line -> {
                deduplicated.remove(line);
                deduplicated.add(line);
            });
        }

        Files.write(path, deduplicated);
    }

}


duke@virtual1:~$ java HistoryCleaner.java

will compile and run the "script".


Shebangs are supported too


#!/usr/bin/java --source 11 -Xmx32m -XX:+UseSerialGC

import java.io....

However, since this is not part of the java language specification, single-file java programs (SFJP) with a #! (shebang) in the first line are technically no regular java files and will not compile when used with javac. This also means that the common file naming conventions are not required for pure SFJPs (i.e. file name does not have to be the same as the class name).

Using a different file extension is advised. We can't call it .js - so lets call it .sfjp :).


duke@virtual1:~$ ./HistoryCleaner.sfjp

This will compile and run the HistoryCleaner SFJP containing the shebang declaration in the first line. Keeping the .java file extension would result in a compiler error. As bonus we can also set JVM flags using the shebang mechanism. Keep in mind that -source [version] must be the first flag to tell the java launcher that it should expect a source file instead of bytecode.




Comments:

Post a Comment:
  • HTML Syntax: NOT allowed