Измените значение find -printf в bash - PullRequest
0 голосов
/ 27 октября 2019

Я использую find для печати строки для каждого файла и каталога:

find ${rootdirectory} -printf '%p,%T@\n' >> ${outputfile}

Однако мне нравится конвертировать %T@ из unixepoch в Windows FILETIME:

filetime=$(( (%T@ + 11644473600) * 10000000 ))
find ${rootdirectory} -printf '%p,${filetime}\n' >> ${outputfile}

Это, конечно, не работает, потому что %T@ не установлен до find -printf.

Каков самый быстрый способ найти миллионы файлов при изменении найденного целого числа? У меня уже есть решение с stat, но оно очень медленное:

find ${rootdirectory} -exec 1>${outputfile} sh -c 'for file in "${1}"/* ;
  do
    unixtime=$(stat -c%Y ${file})
    filetime=$(( (${unixtime} + 11644473600) * 10000000 ))
    stat -c%n,${filetime} ${file}
  done' none {}  \;

Я изменил это на вариант с -printf, но T не распознается:

find ${rootdirectory} -exec 1>${outputfile} sh -c 'for file in "${1}"/* ;
  do
    unixtime=$(printf %T@)
    filetime=$(( (${unixtime} + 11644473600) * 10000000 ))
    -printf %p,${filetime}
  done' none {}  \;

Моя последняя надежда заключалась в следующем:

print_format="%p,$(( %T@ + 11644473600 ))\n"
find ${rootdirectory} -printf "$print_format"

Ради полноты, это не работает:

find ${rootdirectory} -printf '%p,$(( (%T@ + 11644473600) * 10000000 ))\n'

У кого-нибудь есть идеи? И будет ли xargs быстрее exec?

1 Ответ

1 голос
/ 27 октября 2019

«Убийца» в вашем решении (учитывая большое количество файлов) - это повторное выполнение (по одному на файл) «оболочки». Как вы уже указали, 'find' не поддерживает арифметику для оператора.

Одной из альтернатив является использование постпроцессора (awk, Perl, Python), который будет считывать выходные данные из find и выполнять преобразование. .

# Using printf
find ${rootdirectory} -printf '%p,%T@\n' | awk -v FS=, -v OFS=, '{ printf ("%s,%d\n",  $1, ($2+ 11644473600) * 10000000)}'

# On 32 bit environment, using %.0f
find ${rootdirectory} -printf '%p,%T@\n' | awk -v FS=, -v OFS=, '{ printf ("%s,%.0f\n",  $1, ($2+ 11644473600) * 10000000)}'

# Or using regular print
find ${rootdirectory} -printf '%p,%T@\n' | awk -v FS=, -v OFS=, '{ printf ("%s,%d\n",  $1, ($2+ 11644473600) * 10000000)}'

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

Использование xargs может ускорить код, но только если вы используете несколько «громоздких»где большое количество файлов будет обработано одной командой. Вряд ли это будет быстрее, чем «awk» - отдельный процесс.

Использование только решения bash будет сложным, поскольку bash не поддерживает математику для значений с плавающей запятой (на Mint 19, @T включает дробь).

...