2009-12-04 2 views
0
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 

В нем перечислены все java-файлы в дереве src; то для каждого из них он удаляет суффикс «.java» (cut -d '.' -f2, потому что вывод find . имеет префикс .). Затем он использует -nt для проверки того, является ли java-файл в дереве src более новым, чем соответствующий файл класса в дереве сборки; если он новее, он выводится. [javac может затем использовать это, чтобы скомпилировать только необходимые файлы src, вместо использования ant или make]Как можно сравнить эти временные метки src и build tree?

Проблема в том, что она слишком медленная, занимает около 275 мс. Как сделать это быстрее?

Или есть более быстрый способ сделать это в bash? Я не вижу, как это сделать с find, diff, rsync или make (который, кажется, не пересекает деревья автоматически и нуждается в явно перечисленных исходных файлах).

ответ

1

попробовать это:

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

Это не будет рекурсивно обрабатывать поддиры src. –

+0

Я думаю, вы имеете в виду $ {file/.java/.class} в подстановке? –

+0

Спасибо, мне нравятся 'basename $ f' и' $ {file //. Java /} '- я их не знал! В последнем, я думаю, вы имели в виду 'build/$ {file/.java/.class}'. Но 'src/*. Java' и' basename' охватывают только один уровень, а не дерево src (например, вложенные пакеты). – 13ren

0

Принятие подхода Кона к имени файла munging, скорость улучшается от 320ms к 45ms в среднем. Спасибо, 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 

Оригинал немного медленнее (теперь 275 мс, теперь 320 мс); Я не знаю почему. Я использую ту же линию. Возможно, разные источники системы после воспроизведения видео.

EDIT снова сначала в комментарий: коверкая "SRC /" прочь вместо cd src; ... cd -;. Обратите внимание, что оба $n и $n2 используются [Вы не можете гнездо $ {вар/A/B} построить, не так ли?]

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

Я не думаю, что '; Здесь необходим cd -'. – rsp

+0

@rsp Я согласен. '; cd -' отменяет 'cd src;', что необходимо, чтобы один и тот же фрагмент пути мог отображаться как в src, так и в строках. Вместо этого я обновляю этот ответ с помощью имени mangling. – 13ren

+1

Причина '; cd -' не требуется, так это 'cd src; find ... 'выполняются в подоболочке. Когда это выйдет, вы все еще находитесь в родительском каталоге 'src'. –

0

муравей выполняет смарт-логику здания, она не будет строить класс тех пор, пока источник был изменен.

Возможно, вы также захотите посмотреть на scons, который не является встроенным инструментом сборки Java, но очень удобен при компиляции эффективных сложных деревьев сборки и имеет также java-конструктор.

+0

Я использовал муравей, но он слишком медленный. Я взломал свой собственный инструмент сборки, который сокращает время компиляции с 5000 до 250 мс (в среднем). Этот вопрос касается уточнения, которое должно только добавить к нему несколько мс. Я просто смотрел на брахи, но у него нет показателей производительности в faq. Я буду следить за ним, хотя; Благодарю. – 13ren

+0

Я только что попробовал схола; он генерирует команды javac, а это не то, что мне нужно. Кроме того, у меня было много проблем с настройкой: примеры из руководства и 'man scons' не работают так, как есть, и в итоге он не смог найти javac для компиляции. Хотя я настроил среду с помощью инструмента «javac» и передал переменную env JAVA_HOME. Я упоминаю об этом, потому что я предполагаю, что он не очень полезен в качестве инструмента Java, рассматривая ant, IDE и написан на python. Наконец, самый быстрый запуск, который я получил, был 1121 мс (это генерирует команду javac, а не запускает ее). Быстрее, чем муравей, но не для меня. – 13ren

1

Я не знаю, если эта структура будет быстрее, но это может быть стоит попробовать:

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") 

while форма, вероятно, не будет оказывать никакого прироста. Обрушившийся if может. Регулярное выражение может внести небольшой вклад.

Как вы узнали, устранение звонка на cut имеет большое значение.

+0

спасибо, хотя я получаю 'синтаксическую ошибку около' src/(. ''. – 13ren

+0

какая версия bash вы используете? Возможно, она не поддерживает двоичный оператор = ~ – kon

+0

' = ~ 'был введен в 3.0 и там были изменения, которые влияют на совместимость где-то около 3.1 или 3.2. –

Смежные вопросы