我正在尝试就地 OCR 一些文档(从 Windows 共享上的 Linux 命令行)。 OCRing 的过程是 find ,我已经通过使用 find 命令正确地通过循环管道传输文件而糊涂了。
但是我需要保留原始时间戳以进行修改。我目前正在尝试使用 stat 和 touch ,如下所示:
#!/bin/bash
OLDIFS=$IFS
IFS=$(echo -en "\n\b")
for f in `find /mnt/library/Libra/Libra/Ashfords -name "*.pdf"`
do
ORIGTS=`stat -c "%Y" $f`
sudo /opt/ABBYYOCR9/abbyyocr9 -rl English -pi -if $f -f PDFA -paemImageOnText -pafpr original -of $f
touch -t $ORIGTS $f
done
IFS=$OLDIFS
当然,触摸命令失败了。单独运行命令我注意到“stat -c”是这样的:
1334758696
这就像我不知道任何日期一样。我觉得我已经很接近了,但无法弄清楚如何将我的日期转换为触摸友好的版本。是某种形式的秒数吗?
答案1
stat's
输出是 Unix 时间戳,也称为自纪元以来的秒数。
所有接受日期的 GNU coreutils 都允许您通过在时间戳前加上@
.
所以试试这个
touch -d @$ORIGTS $f
答案2
touch
可以使用该选项来使用文件的时间戳-r
。您可能想输出到不同的文件(我假设下面-if
是输入文件和-of
输出文件)
for f in ...; do
sudo /opt/ABBYYOCR9/abbyyocr9 ... -if $f ... -of $f.new
touch -r $f $f.new
mv $f.new $f
done
答案3
IFS=$(echo -en "\n\b")
由于您假设有一个带有 的 shell echo -e
,并且无论如何您的 shebang 行中都有 bash,因此您可以使用IFS=$'\n\b'
.将退格键用作分隔符是相当奇怪的。无论如何,你不需要IFS
你正在做的事情。
OLDIFS=$IFS
……
IFS=$OLDIFS
IFS
请注意,仅当IFS
最初设置时,这才会恢复旧值。如果IFS
最初未设置,则设置IFS
为空字符串,这是完全不同的。在 ksh、bash 或 zsh 中,如果需要IFS
临时设置,可以将代码编写在函数中并使其成为IFS
该函数的本地代码。在其他 shell 中,您需要小心未设置的情况。
`find /mnt/library/Libra/Libra/Ashfords -name "*.pdf"`
切勿对 的输出使用命令替换find
。
- 这会在 中的字符处分割输出
$IFS
。如果您设置IFS
为换行符,那么这会在换行符处分割输出,但您仍然无法处理包含换行符的文件名。 - 命令替换的结果不仅被分割成单词,而且每个单词都被用作一个全局模式。如果你的文件名为
A[12].pdf
,A1.pdf
和A2.pdf
,你最终会得到A1.pdf A2.pdf A1.pdf A2.pdf
.您可以使用 关闭通配符set -f
(并使用 重新打开set +f
),但这里(像大多数时候一样)正确的方法是不要使用命令替换。
使用-exec
参数 to find
(或者如果您的系统有-print0
,则可以使用;如果您需要移植到古老的 Linux 系统或当前具有但没有 的find … -print0 | xargs -0 …
OpenBSD 系统,这仅适用于一次对多个文件执行操作)。-print0
-exec … {} +
ORIGTS=`stat -c "%Y" $f` # [transform $f] touch -t $ORIGTS $f
请注意,您缺少双引号(如果这些是拆分的结果,并且从那时起您没有更改并且关闭了通配符,则$f
不需要它们,但实际上,总是加上双引号,除非您知道为什么可以'IFS
不要让它们打开)。
这是笨拙且不可移植的(stat
并非在所有系统上都存在,并且它的参数在它存在的不同系统中是不同的)。touch
有一个可移植选项,可以将一个文件设置为另一个文件的时间戳:touch -r REFERENCE_FILE FILE
.我会推荐以下两种方法之一:
- 如果可以的话,先将原文件转换成新文件,然后调用
touch -r
设置新文件的日期,最后将新文件移动到位。最好在输入发生任何问题之前确保输出正常;否则,如果转换因任何原因(例如电源故障)中断,您将丢失数据。 - 如果转换是一个您无法控制的黑匣子,您可以使用
touch -r
两次:一次将原始文件的日期保存在空临时文件(将自动创建)上,然后在转换后再次恢复日期使用临时文件。
因此:
find /mnt/library/Libra/Libra/Ashfords -name '*.pdf' \
-exec sh -c 'transform "$0" to "$0.tmp" && touch -r "$0" "$0.tmp" && mv -f "$0.tmp" "$0"' {} \;
答案4
我也遇到了同样的问题,来自“电影制作”过程。
下面的示例中orig_file.wav
是具有原始时间戳的文件,而processed_file.wav
是具有相同内容但时间戳错误的文件。
前:
localhost $ ls -lh orig_file.wav processed_file.wav Jan 23 17:15 processed_file.wav Jul 9 2018 orig_file.wav
命令:
localhost $ touch -t $(date --date=@`stat -f%B orig_file.wav` +%Y%m%d%H%M.%S) processed_file.wav
后:
localhost $ ls -lh orig_file.wav processed_file.wav Jul 9 2018 processed_file.wav Jul 9 2018 orig_file.wav
笔记:
stat
in invertedticks 为您提供原始文件的创建时间戳,作为 unix 纪元时间(以秒为单位)。 coreutils 中的 @ 将其转换为date
可以理解的 iso 日期,并使用 YYYYMMDDHHmm.SS 重新格式化,以便touch
可以理解它。我将date
命令放入 $() 中,相当于反向刻度,因为它们不能在同一命令中重复使用。