Question

for n in `cd src; find . -name "*.java"; cd -`;
  do a=`echo $n | cut -d '.' -f2`;
  if [[ src/$a.java -nt build/$a.class ]];
    then echo src/$a.java;
  fi;
done

It lists all the java files in the src tree; then for each one, it removes the suffix ".java" (cut -d '.' -f2 because find . output is prefixed with .). It then uses -nt to test if the java file in the src tree is newer than the corresponding class file in the build tree; if it is newer, it is output. [javac can then use this to compile only the needed src files, instead of using ant or make]

The problem is that it is too slow, taking about 275ms. How to make it faster?

Or is there a faster way to do this in bash? I can't see how to do it with find, diff, rsync nor make (which doesn't seem to traverse trees automatically, and needs explicitly listed source files).

Was it helpful?

Solution

try this:

for f in src/*.java; do 
  file=`basename $f`; 
  if [[ src/$file -nt build/${file//.java/} ]]; then 
     echo src/$file; 
  fi; 
done 

OTHER TIPS

I don't know if this structure would be any faster, but it might be worth a try:

while read n
do
     # capture the basename all at once
     [[ $n =~ src/(.*)\.java ]]   # escape the parentheses for Bash < 3.2 (or thereabouts)
     [[ $n -nt "build/${BASH_REMATCH[1]}.class" ]] && echo $n
done < <(find src -name "*.java")

The while form probably won't provide any boost. The collapsed if may. The regex might provide a small contribution.

As you've found out, eliminating a call to cut has made the biggest difference.

ant performs smart building logic, it will not build a class unless the source was modified.

You might also like to look into scons which is not a native Java build tool but is very handy at compiling efficient complex build trees and does have java builder as well.

Adopting kon's approach to the filename munging, the speed improves from 320ms to 45ms on average. Thanks kon!

for n in `cd src; find . -name "*.java"; cd -`; do
  if [[ src/$n -nt build/${n/.java/.class} ]];
     then echo src/$n;
  fi;
done

The original is a bit slower now (was 275ms; now 320ms); I don't know why. I'm using the same line. Maybe different system sources after playing a video.

EDIT re rst's comment: mangling the "src/" away instead of cd src; ... cd -;. Note that both $n and $n2 are used [you can't nest the ${var/A/B} construct, can you?]

for n in `find src -name "*.java"`; do
  n2=${n/src/}
  if [[ $n -nt build/${n2/.java/.class} ]];
     then echo $n;
  fi;
done
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top