Чтение файлов по порядку в скрипте BASH - PullRequest
3 голосов
/ 16 февраля 2011

Итак, у меня есть bash-скрипт, который обрабатывает ряд подкаталогов, ищет файлы, содержащие определенную строку, а затем печатает итоговые значения файлов и каталогов для вхождений этой строки.Код выглядит следующим образом.

  for dir in $(find * -type d); do
  echo "directory: $dir" >> $OUT
  for f in $(find $dir/* -type f); do
    echo -n "$(basename $f) " >> $OUT
    grep -c -h $1 $f >> $OUT
  done
  echo -n "directory total: " >> $OUT
  grep -c -h $1 $dir/*.* | awk '{SUM += $1} END {print SUM}' >> $OUT
  done

Когда он делает это, если я читаю в 10 файлах, он перечисляет их в текстовом файле как file1.txt, file10.txt, file2.txt и т. Д. *

Можно ли как-нибудь заставить его напечатать file1.txt, file2.txt, file3.txt и т. Д., И чтобы 10-й файл был фактически указан в порядке?

Я новичок в BASH, поэтому мне просто интересно, знает ли кто-нибудь об этом.Любая помощь с благодарностью.И да, файлы буквально называются file1.txt, file2.txt и т. Д. Это в основном просто для ознакомления со сценариями BASH.

Ответы [ 4 ]

2 голосов
/ 16 февраля 2011
find -type d | while read -r dir
do
    echo "directory: $dir"
    find "$dir" -maxdepth 1 -type f | sort --version-sort | while read -r f
    do
        echo -n "$(basename "$f") "
        grep -c -h "$1" "$f"
    done
    grep -c -h "$1" "$dir/*" | awk -F: '{SUM += $1} END {print "directory total:", SUM}'
done > "$OUT"
  • Переместить перенаправление в конец цикла
  • Используйте while read вместо for, если имена файлов содержат пробелы (при необходимости могут быть приняты дополнительные меры для защиты от некоторых менее распространенных нечетных символов)
  • Процитируйте свои переменные также для защиты пробелов
  • Используйте -maxdepth 1 с внутренним find, чтобы избежать дублирования дублирования
  • Используйте sort --version-sort, чтобы получить имена файлов в нужном вам порядке
  • AWK может печатать текст одновременно с печатью всего
  • Разделитель полей должен быть установлен на двоеточие
  • Вместо echo -n "$(basename "$f") " вы можете использовать echo -n "${f##*/} "
0 голосов
/ 16 февраля 2011

изменить эту строку:

for f in $(find $dir/* -type f); do

к этой строке:

for f in $(find $dir/* -type f | sort --numeric-sort); do
0 голосов
/ 16 февраля 2011

Так что, я думаю, я понял это с помощью вас, ребята, и немного повозился.Не уверен, что это лучший способ, но я закончил с этой работой ...

for f in $(find $dir -type f | cut -d. -f1 | cut -d'e' -f3 | sort -n); do
    echo -n "  file$(basename $f).txt: "
    grep -c -h $1 $dir/"file$f"'.txt'
  done

Очевидно, что это очень специфично для имен файлов, которые у меня были, но было полезно узнать больше об этом.Спасибо

0 голосов
/ 16 февраля 2011

Файлы отсортированы лексикографически (поэтому file10 идет после file1).Если файлы называются file<num>, это проще - вы используете sort -k1.5n для них.В общем случае это сложнее - потребуется несколько разборов, скажите, является ли ваш случай общим:)

Некоторые пункты:

Возможно, вам нужен не find $dir/* -type f, а find $dir -type f.В первом случае вы используете глобальную функцию оболочки.А как насчет подкаталогов?

Кстати, вы можете переписать его следующим образом, чтобы пропустить спам в каждой строке с >> $OUT:

for dir in $(find * -type d); do
  echo "directory: $dir"
  for f in $(find $dir/* -type f); do
    echo -n "$(basename $f) "
    grep -c -h $1 $f
  done
  echo -n "directory total: "
  grep -c -h $1 $dir/*.* | awk '{SUM += $1} END {print SUM}'
done >> $OUT
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...