使用 stat 提供触摸时间戳

使用 stat 提供触摸时间戳

我正在尝试就地 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

coreutils - 自纪元以来的秒数

答案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.pdfA2.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

笔记:

statin invertedticks 为您提供原始文件的创建时间戳,作为 unix 纪元时间(以秒为单位)。 coreutils 中的 @ 将其转换为date可以理解的 iso 日期,并使用 YYYYMMDDHHmm.SS 重新格式化,以便touch可以理解它。我将date命令放入 $() 中,相当于反向刻度,因为它们不能在同一命令中重复使用。

相关内容