statを使用してタッチのタイムスタンプを提供する


11

一部のドキュメントをその場でOCRしようとしています(Windows共有のLinuxコマンドラインから)。OCRのプロセスは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

それは私が知らない日付のようなものです。近くにいるような気がしますが、日付をタッチフレンドリーなバージョンに変換する方法がわかりません。何かからの秒の形ですか?


余談ですが、の使用はIFS珍しいようです。バックスペース(\b)で分割しますか?ヒントについては、unix.stackexchange.com / questions / 9496 /…を参照してください。
ミケル2012

回答:


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

3

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

でシェルを想定していて、echo -eとにかくシバン行にbashがあるので、を使用できますIFS=$'\n\b'。バックスペースをセパレーターにするのはかなり奇妙です。IFSとにかく何をしている必要はありません。

OLDIFS=$IFS

IFS=$OLDIFS

これは、が最初に設定されたIFS場合IFSにのみ、の古い値を復元することに注意してください。もしはIFS、このセットを最初に設定解除されたIFS完全に異なっている空の文字列に。ksh、bash、またはzshでは、IFS一時的に設定する必要がある場合は、関数にコードを記述して、IFSこの関数に対してローカルにすることができます。他のシェルでは、未設定のケースに注意する必要があります。

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

の出力でコマンド置換を使用しないでくださいfind

  • これにより、出力がの文字で分割され$IFSます。IFS改行を設定すると、出力は改行で分割されますが、改行を含むファイル名は処理できません。
  • コマンド置換の結果が単語に分割されるだけでなく、各単語がグロブパターンとして使用されます。あなたが呼ばれるファイルをした場合A[12].pdfA1.pdf及びA2.pdf、あなたがになってしまいますA1.pdf A2.pdf A1.pdf A2.pdf。でグロビングをオフにset -f(およびでオンに戻すset +f)できますが、ここでは(ほとんどの場合と同様)、コマンド置換を使用しないのが正しい方法です。

-execへの引数を使用しますfind(または、システムにがある場合は-print0find … -print0 | xargs -0 …代わりに使用できます。これは、以前のLinuxシステムまたはを備えて-print0いない現在のOpenBSDシステムへの移植性が必要な場合に、一度に複数のファイルを操作する場合にのみ役立ちます-exec … {} +)。

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

周りに二重引用符$fがないことに注意してください(これらが分割の結果でありIFS、それ以降変更されておらず、グロビングがオフになっている場合は必要ありませんが、実際には、二重引用符を配置する理由がわからない限り、常に二重引用符を付けてください) tオンのままにします)。

これは不格好で移植性statがありません(すべてのシステムに存在するわけではなく、その引数は、存在するさまざまなシステム間で異なります)。touchには、ファイルを別のファイルのタイムスタンプに設定するポータブルオプションがあります:touch -r REFERENCE_FILE FILE。代わりに次の2つの方法のいずれかをお勧めします。

  • 可能であれば、最初に元のファイルを新しいファイルに変換し、次にを呼び出しtouch -rて新しいファイルの日付を設定し、最後に新しいファイルを所定の場所に移動します。入力に何かが発生する前に、出力に問題がないことを確認することをお勧めします。そうしないと、変換がなんらかの理由(停電など)で中断された場合、データが失われます。
  • 変換が制御できないブラックボックスである場合、touch -r2回使用できます。1回目は元のファイルの日付を空の一時ファイル(自動的に作成されます)に保存し、次に変換後に再び日付を復元します。一時ファイルを使用します。

したがって:

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 -rtouchBSDライクなフレンドリーな形式でタイムスタンプを取得する方法を次に示します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の@は、それをdateYYYYMMDDHHmm.SSで理解して再フォーマットできるISO日付に変換し、それを理解touchできるようにします。date同じコマンドで再利用できないため、コマンドを$()に入れました。逆ティックと同じです。


(1)これは、Nicholas Rileyの回答とほぼ同じようですが、より複雑です。なぜ誰かがこれではなくこれを使用したいのでしょうか(または、より良いのは、を使用したglenn jackmanの回答touch -rです)。(2)  stat に入れることができます$(…)。1つのコマンドで複数回使用できます。
G-Manは 'Reinstate Monica'を

作成時刻ではなく変更時刻を使用した彼の回答を除いて、あなたは正しいようです。私はこの他の答えに気づきませんでした。あなたは私の投票に反対することができます。
ドミニク

ええと、私に頼めば面白くない。:-)⁠
G-マンは「元に戻すモニカ言う
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.