По теме Make awk efficient (again)
- awk чрезвычайно эффективен, вы ищете способы сделать ваши конкретные сценарии awk более эффективными и сделать сценарий оболочки, который вызывает awk, более эффективным.
Единственное очевидное улучшения производительности, которые я вижу:
- Изменение:
find * -type f -prune -size +1000000c \( ! -iname "_leftover" \) |
while read FILE; do
awk 'script' "$FILE" && rm "$FILE"
done
на что-то вроде (непроверено):
readarray -d '' files < <(find . -type f -prune -size +1000000c \( ! -iname "_leftover" \) -print0) &&
awk 'script' "${files[@]}" &&
rm -f "${files[@]}"
, поэтому вы вызываете awk один раз всего, а не один раз на файл.
Вызов Func_Clean()
всего один раз для всех файлов во всех каталогах вместо одного раза для каждого каталога.
Используйте GNU parallel или аналогичный для запуска Func_Clean()
во всех каталогах параллельно.
Я вижу, вы планируете направить вывод на gzip
для экономии места, это нормально, но имейте в виду, что это будет вам чего-то стоить (idk сколько) с точки зрения времени исполнения. Также, если вы это сделаете, вам нужно закрыть весь выходной конвейер, поскольку , что - это то, что вы пишете из awk, а не только файл в его конце, поэтому ваш код будет примерно таким (непроверено):
{ curr = tolower(substr($0,1,3)) }
curr != prev {
close(Fpath)
Fpath = "gzip -9 -f >> " gensub(/[^[:alnum:]]/,"_","g",curr)
prev = curr
}
{ print | Fpath }
Это не предназначено для ускорения работы, кроме предложенного выше find
, это просто очистка кода в вашем вопросе для уменьшения избыточности и распространенных ошибок (UUO C, отсутствие кавычек, неправильный способ чтения вывода find, неправильное использование >>
vs >
, et c.). Начните с чего-то вроде этого (непроверено и предполагается, что вам нужно разделить выходные файлы для каждого каталога):
#/usr/bin/env bash
clean_in() {
awk '
{
gsub(/^[ \t"'\'']+|[ \t"'\'']+$/, "")
sub(/[,|;: \t]+/, ":")
if (/^[[:alnum:]_.+-]+@[[:alnum:]_.-]+\.[[:alnum:]]+:/ && /^[\x00-\x7F]*$/) {
print
}
else {
print > "_leftover"
}
}
' "${@:--}"
}
split_out() {
local n="$1"
shift
awk -v n="$n" '
{ curr = tolower(substr($0,1,n)) }
curr != prev {
close(Fpath)
Fpath = gensub(/[^[:alnum:]]/,"_","g",curr)
prev = curr
}
{ print > Fpath }
' "${@:--}"
}
Func_Clean() {
local dir="$1"
printf '%s\n' "$dir" >&2
pushd "$dir" > /dev/null
clean_in *.txt |
sort -t':' -k1,1 |
split_out 2 &&
rm -f *.txt &&
readarray -d '' big_files < <(find . -type f -prune -size +1000000c \( ! -iname "_leftover" \) -print0) &&
split_out 3 "${big_files[@]}" &&
rm -f "${big_files[@]}"
popd > /dev/null
}
### MAIN - Starting Point ###
base_folder="_test2"
while IFS= read -r dir; do
Func_Clean "$dir"
done < <(find "$base_folder" -mindepth 1 -type d)
На вашем месте я бы начал с этого (после любого необходимого тестирования / отладки) и ЗАТЕМ поищите способы улучшить производительность.