Verwenden von stat, um einen Zeitstempel für Berührungen bereitzustellen

11

Ich versuche, einige Dokumente in situ zu OCR (über eine Linux-Befehlszeile auf einer Windows-Freigabe). Der Prozess des OCRing ist find und ich habe mich mit dem Befehl find verwirrt, um die Dateien korrekt durch die Schleife zu leiten.

Ich muss jedoch den ursprünglichen Zeitstempel für Änderungen beibehalten. Ich versuche derzeit, stat und touch wie folgt zu verwenden:

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

Natürlich schlägt der Touch-Befehl fehl. Wenn ich die Befehle separat ausführe, stelle ich fest, dass "stat -c" ungefähr so ​​aussieht:

1334758696

Das ist wie kein Datum, das ich kenne. Ich habe das Gefühl, nah dran zu sein, kann aber nicht herausfinden, wie ich das Datum, das ich habe, in eine berührungsfreundliche Version umwandeln kann. Ist es eine Form von Sekunden von etwas?

Tim Alexander
quelle
Nebenbei: Ihre Verwendung von IFSscheint ungewöhnlich. Wollten Sie wirklich auf backspace ( \b) teilen ? Einige Tipps finden Sie unter unix.stackexchange.com/questions/9496/… .
Mikel

Antworten:

16

stat'sDie Ausgabe ist ein Unix-Zeitstempel, der seit der Epoche auch als Sekunden bezeichnet wird .

Bei allen GNU-Coreutils, die ein Datum akzeptieren, können Sie stattdessen einen Zeitstempel setzen, indem Sie dem Zeitstempel einen voranstellen @.

Also versuch das mal

touch -d @$ORIGTS $f

Siehe coreutils - Sekunden seit der Epoche

Mikel
quelle
Ah, das erklärt viele Zeitstempel, die ich jetzt unter Linux gesehen habe! Vielen Dank
Tim Alexander
8

touchkann den Zeitstempel einer Datei mit dieser -rOption verwenden. Möglicherweise möchten Sie in eine andere Datei ausgeben (ich gehe davon aus, dass -ifes sich unten um eine Eingabedatei und -ofeine Ausgabedatei handelt).

for f in ...; do
    sudo /opt/ABBYYOCR9/abbyyocr9 ... -if $f ... -of $f.new
    touch -r $f $f.new
    mv $f.new $f
done
Glenn Jackman
quelle
+1 zur Vermeidung stat.
10.
3

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

Da Sie eine Shell mit annehmen echo -eund ohnehin Bash in Ihrer Shebang-Linie haben, können Sie verwenden IFS=$'\n\b'. Rücktaste zu einem Trennzeichen zu machen ist ziemlich seltsam. Sie brauchen IFSsowieso nicht für das, was Sie tun.

OLDIFS=$IFS

IFS=$OLDIFS

Beachten Sie, dass dadurch der alte Wert von IFSnur wiederhergestellt wird, wenn er IFSursprünglich festgelegt wurde. Wenn dies IFSursprünglich nicht festgelegt wurde IFS, wird die leere Zeichenfolge festgelegt, die völlig anders ist. Wenn Sie in ksh, bash oder zsh IFSvorübergehend festlegen müssen , können Sie Ihren Code in eine Funktion schreiben und IFSdiese Funktion lokalisieren. In anderen Schalen müssen Sie vorsichtig mit dem nicht eingestellten Fall sein.

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

Verwenden Sie niemals die Befehlssubstitution für die Ausgabe von find.

  • Dadurch wird die Ausgabe an den Zeichen in aufgeteilt $IFS. Wenn Sie IFSeine neue Zeile festlegen, wird die Ausgabe in Zeilenumbrüche aufgeteilt, Sie können jedoch weiterhin keine Dateinamen verarbeiten, die Zeilenumbrüche enthalten.
  • Das Ergebnis der Befehlssubstitution wird nicht nur in Wörter aufgeteilt, sondern jedes Wort wird als Glob-Muster verwendet. Wenn Sie Dateien aufgerufen haben A[12].pdf, A1.pdfund A2.pdf, werden Sie am Ende mit A1.pdf A2.pdf A1.pdf A2.pdf. Sie können das Globbing mit set -f(und wieder mit set +f) aktivieren , aber hier (wie meistens) besteht der richtige Weg darin, keine Befehlssubstitution zu verwenden.

Verwenden Sie das -execArgument für find(oder wenn Ihr System dies hat -print0, können Sie es find … -print0 | xargs -0 …stattdessen verwenden; dies ist nur nützlich, um auf mehrere Dateien gleichzeitig zu reagieren, wenn Sie eine Portabilität auf alte Linux-Systeme oder aktuelle OpenBSD-Systeme benötigen, die dies -print0jedoch nicht tun -exec … {} +).

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

Beachten Sie, dass Sie doppelte Anführungszeichen vermissen $f(diese werden nicht benötigt, wenn dies das Ergebnis der Aufteilung ist und Sie sich seitdem nicht geändert haben IFSund das Globbing deaktiviert ist. Setzen Sie jedoch immer doppelte Anführungszeichen, es sei denn, Sie wissen, warum Sie dies können. ' t lass sie an).

Dies ist umständlich und nicht portierbar ( statexistiert nicht auf allen Systemen, und seine Argumente unterscheiden sich zwischen den verschiedenen Systemen, auf denen es existiert). touchhat eine tragbare Option, um eine Datei auf den Zeitstempel einer anderen Datei zu setzen : touch -r REFERENCE_FILE FILE. Ich würde stattdessen einen von zwei Ansätzen empfehlen:

  • Wenn Sie können, wandeln Sie zuerst die Originaldatei in eine neue Datei um, rufen Sie dann touch -rauf, um das Datum der neuen Datei festzulegen, und verschieben Sie die neue Datei schließlich an ihren Platz. Es ist besser sicherzustellen, dass die Ausgabe in Ordnung ist, bevor etwas mit der Eingabe passiert. Andernfalls gehen Daten verloren, wenn die Umwandlung aus irgendeinem Grund unterbrochen wird (z. B. aufgrund eines Stromausfalls).
  • Wenn es sich bei der Umwandlung um eine Black Box handelt, über die Sie keine Kontrolle haben, können Sie sie touch -rzweimal verwenden: einmal, um das Datum der Originaldatei in einer leeren temporären Datei zu speichern (die automatisch erstellt wird), und erneut nach der Umwandlung, um das Datum wiederherzustellen Verwenden der temporären Datei.

Somit:

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"' {} \;
Gilles 'SO - hör auf böse zu sein'
quelle
0

Aus irgendeinem Grund habe ich die Antwort über verpasst touch -r; Wenn Sie aus irgendeinem seltsamen Grund weder GNU-Coreutils statwie in der akzeptierten Antwort haben noch verwenden können touch -r, toucherfahren Sie hier, wie Sie den Zeitstempel in einem freundlichen Format mit einem BSD-ähnlichen Format erhalten 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

Aber wirklich, benutze einfach touch -r:

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

Ich hatte das gleiche Problem, als ich aus dem "Filmemachen" kam.

Im folgenden Beispiel orig_file.wavbefindet sich die Datei mit dem ursprünglichen Zeitstempel, während processed_file.wavdie Datei denselben Inhalt, aber falschen Zeitstempel aufweist.

VOR:

localhost $ ls -lh orig_file.wav processed_file.wav Jan 23 17:15 processed_file.wav Jul 9 2018 orig_file.wav

DER BEFEHL:

localhost $ touch -t $(date --date=@`stat -f%B orig_file.wav` +%Y%m%d%H%M.%S) processed_file.wav

NACH:

localhost $ ls -lh orig_file.wav processed_file.wav Jul 9 2018 processed_file.wav Jul 9 2018 orig_file.wav

ANMERKUNGEN:

statIn invertierten Ticks erhalten Sie den Erstellungszeitstempel der Originaldatei als Unix-Epochenzeit (in Sekunden). Das @ von coreutils konvertiert es in ein ISO-Datum, datedas YYYYMMDDHHmm.SS verstehen und neu formatieren touchkann, damit es es verstehen kann. Ich habe den dateBefehl in $ () als Äquivalent zu invertierten Ticks eingefügt, da diese nicht im selben Befehl wiederverwendet werden können.

dominikz
quelle
(1) Dies scheint fast genau die gleiche zu sein wie Nicholas Rileys Antwort, ist jedoch komplizierter. Warum sollte jemand dies eher als das verwenden wollen (oder, noch besser, Glenn Jackmans Antwort mit touch -r)? (2)  stat kann eingegeben werden $(…); Sie können in einem Befehl mehrfach verwendet werden.
G-Man sagt "Reinstate Monica"
Abgesehen von seiner Antwort, bei der die Änderungszeit anstelle der Erstellungszeit verwendet wird, scheinen Sie korrekt zu sein. Ich habe diese andere Antwort nicht bemerkt. Sie können meine abstimmen.
Dominikz
Wenn du mich darum bittest, macht es keinen Spaß. :-) ⁠
G-Man sagt 'Reinstate Monica'