С помощью zsh
вы можете определить такую функцию, как:
istext() [[ $(file -b --mime-type -- "${1-$REPLY}") = text/* ]]
Которые затем можно было бы использовать в квалификаторах glob, таких как:
less -- *(.L+0+istext)
Для просмотра не -пустых(L+0
длины больше 0 )обычных файлов(.
)в текущем каталоге, которые являются текстовыми в соответствии с file
.
Пожалуйста, не делайте этого в оболочке. Не существует количества настроек, которые когда-либо сделали бы его удаленно эффективным. Циклы оболочки медленные , и использование оболочки для разбора текста — просто плохая практика. Весь ваш скрипт можно заменить этим простым awk
одним -лайнером, который будет работать на порядки быстрее:
awk 'BEGIN{E = exp(1);} $1>0{tot+=log($1); c++} END{m=tot/c; printf "%.2f\n", E^m}' file
Например, если я запускаю это для файла, содержащего числа от 1 до 100, я получаю:
$ seq 100 > file
$ awk 'BEGIN{E = exp(1);} $1>0{tot+=log($1); c++} END{m=tot/c; printf "%.2f\n", E^m}' file
37.99
Что касается скорости, я протестировал ваше решение для оболочки, ваше решение для python и awk, который я указал выше, на файле, содержащем числа от 1 до 10000:
## Shell
$ time foo.sh
3677.54
real 1m0.720s
user 0m48.720s
sys 0m24.733s
### Python
$ time foo.py
The Geometric Mean is: 3680.827182220091
real 0m0.149s
user 0m0.121s
sys 0m0.027s
### Awk
$ time awk 'BEGIN{E = exp(1);} $1>0{tot+=log($1); c++} END{m=tot/c; printf "%.2f\n", E^m}' input.txt
3680.83
real 0m0.011s
user 0m0.010s
sys 0m0.001s
Как видите, awk
работает даже быстрее, чем Python, и его намного проще писать. Вы также можете превратить его в сценарий «оболочки», если хотите. Либо вот так:
#!/bin/awk -f
BEGIN{
E = exp(1);
}
$1>0{
tot+=log($1);
c++;
}
END{
m=tot/c; printf "%.2f\n", E^m
}
или сохранив команду в сценарии оболочки:
#!/bin/sh
awk 'BEGIN{E = exp(1);} $1>0{tot+=log($1); c++;} END{m=tot/c; printf "%.2f\n", E^m}' "$1"
Вот несколько советов. Я не могу проверить их, не зная точно, что находится в вашем файле, но я надеюсь, что это поможет. Всегда есть разные, лучшие способы сделать что-то, так что это вовсе не исчерпывающий список.
if (( $(echo " "$i" > "0" " | bc -l) )); then
Измените его на:
if [[ "$i" -gt 0 ]]; then
Первая строка создает несколько процессов, даже если она выполняет простую математику. Решение состоит в том, чтобы использовать ключевое слово оболочки [[
.
else
total="$total"
По сути, это способ явно тратить время на ничегонеделание :). Эти 2 строки можно удалить сразу.