Странная проблема с cut, colrm, awk и sed: невозможно вырезать символы из потока - PullRequest
3 голосов
/ 25 января 2011

Я создал скрипт для перечисления всех файлов в каталоге и под ним.Я хотел добавить обратную связь с помощью pv, потому что я обычно использую его из корневого каталога.

Проблема в том, что find всегда включает дробные секунды в свое время (% TT), но я не хочу записывать так много деталей.

Если я напишу сценарий для выполнения всех действий за один проход, я получу правильный вывод.Но если я использую промежуточные файлы для оценки во время второго прохода, результат меняется, и я не понимаю, почему.

Эта версия дает правильный результат:

#!/bin/bash

find -printf "%11s %TY-%Tm-%Td %TT %p\n" 2> /dev/null |
# - Remove the fractional seconds from the time
# before:       4096 2011-01-19 22:43:51.0000000000 .
# after :       4096 2011-01-19 22:43:51 .
colrm 32 42 |
pv -ltrbN "Enumerating files..." |
# - Sort every thing by filename
sort -k 4

Носортировка может занять много времени, поэтому я попробовал что-то вроде этого, чтобы получить немного больше обратной связи:

#!/bin/bash

TMPFILE1=$(mktemp)
TMPFILE2=$(mktemp)

# Erase temporary files before quitting
trap "rm $TMPFILE1 $TMPFILE2" EXIT

find -printf "%11s %TY-%Tm-%Td %TT %p\n" 2> /dev/null |
pv -ltrbN "Enumerating files..." > $TMPFILE1
LINE_COUNT="$(wc -l $TMPFILE1)"

#cat $TMPFILE1 | colrm 32 42 |                   #1
#cat $TMPFILE1 | cut -c1-31,43- |                #2
#cut -c1-31,43- $TMPFILE1 |                      #3
#sed s/.0000000000// $TMPFILE1 |                 #4
awk -F".0000000000" '{print $1 $2}' $TMPFILE1 |  #5
pv -lN "Removing fractional seconds..." -s $LINE_COUNT > $TMPFILE2

echo "Sorting list by filenames..." >&2
cat $TMPFILE2 |
sort -k 4

Ни одно из 5 «решений» не работает.Часть «.0000000000» остается в выводе.

Может кто-нибудь объяснить, почему?

Мое окончательное решение - объединить операцию резки с поиском и использовать только один временный файл.Только сортировка выполняется отдельно.

Ответы [ 2 ]

3 голосов
/ 25 января 2011

Вы можете усечь секунды в аргументе до -printf, используя спецификатор точности поля (по крайней мере, используя GNU find 4.4.2):

find -printf "%11s %TY-%Tm-%Td %.8TT %p\n"

, что оставляет восемь символов в "ЧЧ: MM: SS ".

Остальная часть моего ответа, вероятно, спорная:

Причина, по которой ваш # 1-5 не работает, состоит в том, что вывод wc включает имя файла (и особенно космос).Пробел заставляет pv видеть имя файла из команды wc в качестве входного файла.Аргумент командной строки имеет более высокий приоритет, чем стандартный ввод.Поскольку он совпадает с входным файлом, который передается по каналу, выходной файл выглядит как необработанный входной файл (потому что это так, поскольку конвейер игнорируется).

Для захвата только счетчикабез имени файла:

LINE_COUNT=$(wc -l < "$TMPFILE1")

Вот некоторые незначительные улучшения:

< $TMPFILE1 colrm 32 42 |                   #1 No need for cat

или

colrm 32 42 < $TMPFILE1 |                   #1

< $TMPFILE1 cut -c1-31,43- |                #2

или

cut -c1-31,43- < $TMPFILE1 |                #2

sed s/\.0000000000// $TMPFILE1 |            #4 The dot should be escaped
0 голосов
/ 25 января 2011

Если бы это действительно рабочий инструмент, а не просто игрушка, то я бы просто отбросил «обратную связь о прогрессе» все вместе ... возможно, вернусь к ней, когда она не усложнит вашу жизнь.В то же время вы, вероятно, потратили больше времени, пытаясь выяснить, как дать отзыв, чем потратили время на ожидание возврата вашего скрипта.

Если вы абсолютно ДОЛЖНЫ дать какую-то обратную связь, тогда просто повторяйте "Сортировкаwc -l $TMPFILE строк ... "

У вас будет ощущение, сколько времени потребуется, чтобы отсортировать так много строк из опыта.

Поцелуй его, мой сын, поцелуй его.

...