We’ll try to stay in the project root if possible.
Find all non-hidden files to know the file structure.
$ find -path './.*' -prune -o -type f -print
./Algo-init.iml
./out/production/Algo-init/fr/eql/ai114/algo/init/demo/_1_HelloWorld.class
./src/fr/eql/ai114/algo/init/demo/_1_HelloWorld.java
-
-prune
returns true for the chosen path and preventsfind
from descending. -
-o
means OR, so the paths matching-prune
won’t pass through-o
. -
-type f
selects files, not folders. -
By default, AND is used to connect different conditions.
-
-print
is needed here. It’s often omitted since it’s the default action.Without
-print
,find -path './.*' -prune -o -type f
is interpreted as
find . \(-path './.*' -prune -o -type f \) -print # WRONG!
The above line will also print the current directory
.
, which is not something that we want.The
-print
should stay on the same side of-o
with-type f
.
Find all hidden files.
$ find -path './.*' -type f -print
./.gitignore
./.idea/.gitignore
./.idea/misc.xml
./.idea/modules.xml
./.idea/workspace.xml
We need to extract both the package name and the class name from the source code. It would be a good idea to use shell variables and substitutions to make the commands easier to type.
Extract the relative path of the Java source code file.
$ JAVA_SRC_RELPATH=$(find -name '*.java')
$ cat $JAVA_SRC_RELPATH
package fr.eql.ai114.algo.init.demo;
public class _1_HelloWorld {
public static void main(String[] args) {
// Impression simple
System.out.print("Hello World !");
// Impression avec saut de ligne
System.out.println("Hello World !");
}
}
If I find
from ./src/
instead of ./
, the output won’t begin with ./src
.
That complicates the upcomining commands as we’re staying at the project’s root.
Extract the package name.
$ PKG=$(awk '/^package / { print $NF }' $JAVA_SRC_RELPATH | tr -d ';')
$ echo $PKG
fr.eql.ai114.algo.init.demo
awk
searches lines in the source file starting frompackage
, and print the last field (determined by the system’sIFS
(input field separator)), then- trim the final semicolon
;
(head -c -2
would trim both;
and the trailing newline\n
). - Store it to the shell variable
PKG
.
Extract the class name.
$ CLASS=$(echo ${JAVA_SRC_RELPATH##.*/} | cut -d '.' -f1)
$ echo $CLASS
_1_HelloWorld
- To keep the source file name only, trim the path of the folder containing
that file by a greedy search for
.*/
, then use##
enclosed with${}
for shell substitution, so that we have_1_HelloWorld.java
. - Split this string into two fields using
cut
with the delimiter-d '.'
, and select the first field using-f1
. - Store it to the shell variable
CLASS
.
Execute the program.
$ cd out/production/Algo-init/
$ java $PKG.$CLASS
Hello World !Hello World !
A more in-depth analysis of the output with hexdump
. Unluckily, it doesn’t
come with Git Bash, so we’ll add a bunch of options to od
so that od
imitates the behavior of hexdump
.
$ java $PKG.$CLASS | od -A x -t x1z -v
000000 48 65 6c 6c 6f 20 57 6f 72 6c 64 20 21 48 65 6c >Hello World !Hel<
000010 6c 6f 20 57 6f 72 6c 64 20 21 0d 0a >lo World !..<
00001c
$ java $PKG.$CLASS | od -A x -t x1 -c
000000 48 65 6c 6c 6f 20 57 6f 72 6c 64 20 21 48 65 6c
H e l l o W o r l d ! H e l
000010 6c 6f 20 57 6f 72 6c 64 20 21 0d 0a
l o W o r l d ! \r \n
00001c
$ java $PKG.$CLASS | od -A x -t x -c
000000 6c6c6548 6f57206f 20646c72 6c654821
H e l l o W o r l d ! H e l
000010 57206f6c 646c726f 0a0d2120
l o W o r l d ! \r \n
00001c
$ java $PKG.$CLASS | od -A d -t x1 -c
0000000 48 65 6c 6c 6f 20 57 6f 72 6c 64 20 21 48 65 6c
H e l l o W o r l d ! H e l
0000016 6c 6f 20 57 6f 72 6c 64 20 21 0d 0a
l o W o r l d ! \r \n
0000028
Explanation of the four commands:
od
giveshexdump
-like output. I’m not satisfied with this because I don’t see what\r
and\n
are.- I replaced
z
in-t x1z
by-c
, so that below the hexadecimals-t x1
, we have the printable characters and escape characters-c
. - To see why
1
in-t x1z
is needed, I’ve taken it away, and in the hex code display, we observe that the output is grouped into blocks of 4-byte unit, then inverted before being transcoded into hexadecimals. For example,- at the beginning,
H
,e
l
,l
correspond to hexadecimals48
,65
,6c
and6c
respectively. - The order of these four characters is reversed to give
l
,l
,e
,H
, which correspond to6c
,6c
,65
and48
. - The previous sequence of four hexadecimals are concatenated to give
6c6c6548
in the first line ofod
’s output.
- at the beginning,
- I changed
-A x
to-A d
, so the the leftmost column becomes a decimal number. Observe that 1C₁₆ = 1 × 16 + 12 × 1 = 28.
References:
- How to use ‘-prune’ option of ‘find’ in sh? on Stack Overflow
- Find command: 15 examples to exclude on the Unix School