Обратите внимание, что {1..20}
не является оператором подстановки символов / подстановки. Это особая форма раскрытия фигурных скобок. автор zsh
и скопирован с ограничениями и вариациями ksh93
и bash
.
foo_ {0001..0030} .nc
не расширяется в список совпадающих файлов он расширяется до foo_0001.nc
, foo_0002.nc
, ... foo_0030.nc
независимо от того, являются ли файлы e xist или нет.
bash
имеет то ограничение, что содержимое не может быть изменяемым. ksh93
и zsh
не имеют этого ограничения.
Итак ls -d foo _ {$ ns .. $ ne}.nc
будет работать в этих оболочках.
zsh
также имеет оператор подстановки / подстановки для сопоставления диапазонов десятичных чисел.
ls -d foo_<1-30>.nc
Будет расширен до списка совпадающих файлов. Если вы хотите ограничить его четырьмя цифрами, дополненными нулями, вам понадобится другой оператор:
ls -d foo_(<1-30>~^????).nc # needs extendedglob
( ~
is кроме ( and-not ) ), ^
равно не , поэтому ~ ^
равно , а не-не , поэтому и ).
Оператор
не работает с переменными (поскольку он перекрывается с операторами перенаправления, он работает только при следовании <[цифры] - [цифры]>
шаблон, чтобы максимально избежать конфликтов с перенаправлениями). Однако вы можете использовать этот синтаксис, чтобы обойти это:
ls -d ${~:-foo_<$ns-$ne>.nc}
Или более разборчиво:
pattern="foo_<$ns-$ne>.nc"
ls -d $~pattern
Что-то вроде ls | sed -e 's / \. [0-9] \ + $ //' | сортировать | uniq -c
должен делать то, что вы хотите.
Другой подход: ls | вырезать -f1 -d. | uniq -c
.
awk
подход: ls | awk -F. '{a [$ 1] ++} END {for (b in a) {print b, a [b]}}'
(длинный) perl
подход: ls | perl -e 'while (<>) {$ a {(split (/\./,$_)) [0]} ++} for (ключи сортировки% a) {print "$ _ $ a {$ _} \ n "} '
Я бы не советовал анализировать вывод ls
, find
и т. д. (см. ParsingLs — Wiki Грега для объяснения, почему это плохая идея).
Вместо этого расширение параметров в массиве bash может создать список без расширений файлов.
filelist=(*); # or filelist=(*.log.*) to be more precise
printf '%q\n' "${filelist[@]%.*}" # or echo "${filelist[@]%.*}"
Затем, чтобы работать с файлами по отдельности..
for i in "${filelist[@]%.*}"; do
echo "$i";
done
Для конкретной цели OP мы можем использовать bash ассоциативный массив для хранения количества версий.
filelist=(*.log.*)
declare -A count
for i in "${filelist[@]%.*}"; do
(( count["$i"]++ ));
done
for j in "${!count[@]}"; do
printf '%q\t%q\n' "$j" "${count[$j]}";
done | sort
report01.log 6
report02.log 6
report03.log 6
report04.log 6
report05.log 6