Вывод (и подсчета) дублировать на JS/Java-файлы


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

printf "\nDuplicate JS Filenames...\n"
(
  find . -name '*.js' -type f -exec basename {} \; | sort | uniq -c | grep -v "^[ \t]*1 ";
  echo "$(find . -type f -name '*.js' | wc -l) JS files in search directory";
  echo "$(find . -name '*.js' -type f -exec basename {} \; | sort | uniq -c | grep -v "^[ \t]*1 " | wc -l) duplicates found";
)

printf "\nDuplicate Java Filenames...\n"
(
  find . -name '*.java' -type f -exec basename {} \; | sort | uniq -c | grep -v "^[ \t]*1 ";
  echo "$(find . -type f -name '*.java' | wc -l) Java files in search directory";
  echo "$(find . -name '*.java' -type f -exec basename {} \; | sort | uniq -c | grep -v "^[ \t]*1 " | wc -l) duplicates found";
)

Я знаю, что я делаю тот же запрос, или похожие на них, пару раз.

Как я могу оптимизировать это, и, возможно, уже в базовой команде - я удивлен, что найти так долго, или это из-за сортировки, уник, и grep?



105
2
задан 22 марта 2018 в 12:03 Источник Поделиться
Комментарии
1 ответ

В стороне от работы по сути тот же find команда три раза, главной проблемой является то, что отдельный basename экземпляр для каждого найденного файла.

Если вы используете GNU find (проверьте с find --version), вы можете найти, чтобы распечатать имена напрямую:

find . -name '*.js' -type f -printf '%f\n'

На моей системе это около 900 раз быстрее, чем звонить basename при запуске в директории с около 200 000 файлов в нем.

Если ваша система не приходят с GNU find (например, в macOS, в OpenBSD, FreeBSD) и вы не хотите, чтобы установить его (пакет обычно называется findutils), вы можете использовать sed делать так же, как basename но для всех найденных файлов сразу:

find . -name '*.js' -type f | sed 's@.*/@@'

На моей системе это лишь немногим медленнее, чем при использовании -printf.


Если вы хотите уменьшить количество раз, когда вы запустите findвы можете просто сохранить результат в переменную:

filelist="$(find . -name '*.js' -type f -printf '%f\n' | sort)"
echo "$filelist" | uniq -c | grep -v "^[ \t]*1 ";
echo "$(echo "$filelist" | wc -l) JS files in search directory";
echo "$(echo "$filelist" | uniq -c | grep -v "^[ \t]*1 " | wc -l) duplicates found"

Обратите внимание, что на bash вы должны поставить двойные кавычки вокруг $filelist так что строки не раздавил.

5
ответ дан 22 марта 2018 в 02:03 Источник Поделиться