Циклический подсчет файлов

whereis python | sed 's/ /\n/g' | sort | uniq

Тогда у сортировки много вариантов

Если вы хотите изменить порядок:

whereis python | sed 's/ /\n/g' | sort -r | uniq

-r, --reverse
    reverse the result of comparisons

если бы вы (могли )иметь несколько странных двоичных/исходных/ручных файлов, содержащих специальные символы:

-i, --ignore-nonprinting
    consider only printable characters
0
24.09.2019, 15:56
7 ответов

Попробуйте это,

Count=0
for i in {$start..$stop}; do
   Counter="$(ls /home/me/*/file_$i.txt 2> /dev/null | wc -l)"
   Count=$((Count+Counter))
done
echo "$Count"
1
28.01.2020, 02:22

Если я вас правильно понял, цикл не нужен:

Допустим, диапазон от 12 до 76:

ls -l | grep -e "file_1[2-9].txt" -e "file_[2-6][0-9].txt" -e "file_7[0-6].txt"

Файлы с 12 по 19

"file_1[2-9].txt"

Файлы с 20 по 69:

"file_[2-6][0-9].txt"

Файлы с 70 по 76

"file_7[0-6].txt"
0
28.01.2020, 02:22

Не используйте цикл вообще. Вместо этого перечислите все файлы и используйте команду, например grepили akw, чтобы отфильтровать файлы между startи stop. printfне будет иметь проблем Argument list too long, так как это bashвстроенный -.

printf '%s\0' /home/me/*/file_*.txt |
grep -cEzf <(seq "$start" "$stop" | sed 's/.*/_&\.txt$/')

Здесь мы предполагаем, что у вас есть версии GNU grep, которые могут обрабатывать нулевые байты. Это важно для безопасной обработки путей. Нулевой байт — единственный символ, который не может быть частью пути, поэтому мы можем использовать его для разделения путей.
Если у вас нет версии GNU, вы можете создать что-то, что разделяет пути символами новой строки, предполагая, что ни один из путей не содержит символ новой строки. Замените \0на \nи снимите флаг -z.

Если вы измените …_*.txtна что-то другое, возможно, вам также придется обновить команду sed.

1
28.01.2020, 02:22

A bashрешение:

(
shopt -s nullglob
start=1   # change as needed
stop=500  # change as needed
printf '%s\n' $(printf '/home/me/*/file_%s.txt\n' $(seq "$start" "$stop")) | wc -l
)

Включите nullglob, чтобы сопоставлять только существующие файлы и выполнять скрипт в подоболочке (…), поэтому нам не нужно определять предыдущее состояние nullglobи сбрасывать его старое состояние по завершении. Внутренний printfиспользуется для генерации всех возможных шаблонов имен файлов, а внешний printfнеобходим для интерпретировать *как символ глобуса. Напечатанные выходные строки подсчитываются с помощью wc -l.

0
28.01.2020, 02:22

Вы можете использовать подстановку процесса и grep -f для поиска только файлов в пределах диапазона.

. Для подсчета всех файлов с именем file _[0 -9]+.txt в диапазоне от 10 до 20:

start=10
end=20
ls -f1 | grep -F -f <(printf "file_%s.txt\n" $(seq ${start} ${end}))|wc -l
0
28.01.2020, 02:22
  1. Не используйте eval, если у вас нет другой альтернативы. Это потенциально опасно, в зависимости от содержимого переменных $startи $stop. Не стоит привыкать использовать его там, где он не нужен.

  2. Не используйте вывод lsни для чего, кроме просмотра в терминале. Попытка разобрать ls, даже самым простым способом, может привести к неудаче во многих отношениях. Используйте любое , которое может создать список имен файлов, разделенных NUL -, вместо:find -print0часто является хорошим выбором.

  3. bash, встроенный -в расширение последовательности {x..y}, не может оценивать переменные, но отдельная программа seqможет принимать переменные в качестве аргументов. Он также имеет полезную опцию -sдля указания разделителя.

Для следующего требуется версия grep, которая поддерживает параметр -zдля разделенных входных записей NUL -(, например. GNU, FreeBSD и большинство других современных версий grep).

# build a regular expression matching the desired sequence
re="$(seq -s '|' "$start" "$stop")"

# use the RE with `find... -print0` and `grep -E -z -c`
find /home/me/*/ -maxdepth 1 -type f -name 'file_*.txt' -print0 | 
  grep -Ezc "/file_($re)\.txt$"

Например, если start=3и stop=7, то $reбудет 3|4|5|6|7. Затем команда grepрасширится до :

.
grep -Ezc "/file_(3|4|5|6|7)\.txt$"

Кстати, аргументы -name 'file_*.txt'для команды findне требуются.Их можно отбросить, и конвейер все равно будет работать без ошибок. Все, что они делают, это сокращают входные данные, которые необходимо обработать с помощью grep. В лучшем случае очень незначительная оптимизация.

напр.

find /home/me/*/ -maxdepth 1 -type f -print0 | grep -Ezc "/file_($re)\.txt$"
1
28.01.2020, 02:22

Сzsh:

count=0 range="<$start-$stop>"
/home/me/*/file_$~range.txt(Ne['((!++count))'])

Дает подсчет без сохранения списка файлов в памяти.

  • <1-100>- это оператор zsh glob, который соответствует десятичным числам в этом диапазоне (обратите внимание, что он соответствует 2, но также и 000002, например)
  • $~varаналогичен $var, за исключением того, что содержимое $varрассматривается как шаблон, а не буквальное значение.
  • (Ne['code'])является квалификатором глобуса
  • N:включает nullglobдля этого шаблона, чтобы он не терпел неудачу, если глобус не соответствует ни одному файлу (, что всегда имеет место здесь ).
  • e['code']выбирает файлы на основе оценки code. Здесь код(((!++count)))увеличивает $countи всегда возвращает false, поэтому файлы не выбираются (, а $countувеличиваются, и это все, что нас здесь интересует ).
0
28.01.2020, 02:22

Теги

Похожие вопросы