在bash中更改find-printf的值



我使用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快吗?

解决方案中的"杀手"(给定大量文件(是"shell"的重复执行(每个文件一个(。正如您已经指出的,"find"不支持运算符上的算术运算。

一种选择是使用后处理器(awk、Perl、Python(,它将读取find的输出并执行转换。

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

如果只调用一次awk,这将比尝试的解决方案快得多。

使用xargs可以加快代码的速度,但前提是您使用一些"膨胀",即通过一个命令处理大量文件。它不太可能比"awk"(单个进程(更快。

仅使用bash的解决方案将很困难,因为bash不支持浮点值的数学运算(在Mint 19上,@T包括分数(。

最新更新