使用统计信息提供触摸的时间戳


11

我正在尝试对某些文档进行OCR(从Windows共享上的Linux命令行)。OCRing的过程已找到,而我已经使用find命令使文件正确地通过循环传输了。

但是,我需要保留原始时间戳以进行修改。我目前正在尝试使用stat并触摸如下:

#!/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

这就像我不知道约会一样。我感觉好像已经接近了,但是无法解决如何将我的约会日期转换为触摸友好版本。是某种形式的几秒钟?


撇开:您对的使用IFS似乎很不正常。您是否真的要在Backspace(\b)上分割?有关一些提示,请参见unix.stackexchange.com/questions/9496/…
Mikel

Answers:


17

stat's输出是Unix时间戳,也称为距Epoch的秒

所有接受日期的GNU coreutils都允许您放置时间戳,而不是在时间戳前面加上@

所以试试这个

touch -d @$ORIGTS $f

请参阅coreutils-自纪元以来的秒数


啊,这解释了我现在在Linux中看到的很多时间戳!非常感谢
Tim Alexander

8

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

为避免+1 stat
l0b0 2012年

3

IFS=$(echo -en "\n\b")

由于您假设使用的外壳echo -e,并且无论如何在shebang行中都有bash,因此可以使用IFS=$'\n\b'。将退格分隔符分隔是很奇怪的。IFS无论如何,您都不需要做任何事情。

OLDIFS=$IFS

IFS=$OLDIFS

请注意,这IFSIFS在初始设置时恢复旧值。如果IFS最初未设置,则设置IFS为空字符串,这是完全不同的。在ksh,bash或zsh中,如果需要IFS临时设置,则可以在函数中编写代码并将其IFS局部化。在其他Shell中,您需要注意未设置的情况。

`find /mnt/library/Libra/Libra/Ashfords -name "*.pdf"`

切勿在的输出上使用命令替换find

  • 这会将输出分割为中的字符$IFS。如果设置IFS为换行符,则这将在换行符处分割输出,但仍无法处理包含换行符的文件名。
  • 命令替换的结果不仅会分解为单词,而且每个单词都将用作全局模式。如果文件叫A[12].pdfA1.pdfA2.pdf,你就结了A1.pdf A2.pdf A1.pdf A2.pdf。您可以使用set -f(关闭,然后再使用set +f)关闭切换功能,但是在这里(大多数情况下),正确的方法是不使用命令替换。

使用-exec参数来代替find(或者,如果您的系统具有-print0,则可以使用find … -print0 | xargs -0 …;可以使用该参数;仅当您需要可移植到古老的Linux系统或具有-print0但不具备的当前OpenBSD系统时,才可以一次作用于多个文件-exec … {} +)。

ORIGTS=`stat -c "%Y" $f`
# [transform $f]
touch -t $ORIGTS $f

请注意,您会丢失双引号$f(如果这些是拆分的结果,并且IFS自那时以来您就没有更改过,并且关闭了globbing,则不需要双引号,但实际上,除非您知道为什么可以,否则始终使用双引号。不要把它们放在身上)。

这是笨拙且不可移植的(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"' {} \;

0

由于某种原因我错过了关于的答案touch -r; 如果出于某种奇怪的原因,您既没有stat接受的答案中的GNU coreutils ,也无法使用touch -r,请按照以下方法使用touch类似BSD 的时间戳获取友好格式的时间戳stat

% /usr/bin/stat -f '%Sm' johnson                   
Oct 23 22:51:00 2012
% /usr/bin/stat -t '%Y%m%d%H%M.%S' -f '%Sm' johnson
201210232251.00
% touch foo
% touch -t $(/usr/bin/stat -t '%Y%m%d%H%M.%S' -f '%Sm' johnson) foo
% /usr/bin/stat -f '%Sm' foo                    
Oct 23 22:51:00 2012

但实际上,只需使用touch -r

% touch foo
% touch -r johnson foo
% /usr/bin/stat -f '%Sm' foo
Oct 23 22:51:00 2012

0

我有同样的问题,来自“电影制作”过程。

在下面的示例中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以倒勾表示的时间为您提供原始文件的创建时间戳记,以Unix纪元时间(以秒为单位)。来自coreutils的@将其转换为date可以理解并用YYYYMMDDHHmm.SS重新格式化的iso日期,以便touch可以理解它。我将date命令放入$()中,等效于反向滴答,因为它们不能在同一命令中重复使用。


(1)这似乎与尼古拉斯·赖利Nicholas Riley)的回答几乎完全相同,但更为复杂。为什么有人要使用这个而不是那个(或者更好的是,glenn jackman的答案,使用touch -r)?(2)  stat 可以放入$(…);它们可以在一个命令中多次使用。
G-Man说'

除了他使用修改时间而不是创建时间的答案外,您似乎是正确的。我没有注意到这个其他答案。您可以拒绝我的投票。
dominikz

好吧,如果您要我这样做,那没什么好玩的。:-)⁠
G-人说'恢复莫妮卡'
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.