используя stat для предоставления метки времени для прикосновения


11

Я пытаюсь OCR некоторые документы insitu (из командной строки Linux на общий ресурс Windows). Процесс OCRing - это поиск, и я запутался в использовании команды 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кажется необычным. Вы действительно хотели разделить Backspace ( \b)? См. Unix.stackexchange.com/questions/9496/… за некоторыми советами.
Микель

Ответы:


17

stat'soutput - это метка времени Unix, также называемая секундами с начала эпохи .

Все coreutils GNU, которые принимают дату, позволяют вместо этого поставить временную метку, поставив перед ней метку @.

Так попробуй это

touch -d @$ORIGTS $f

Смотрите coreutils - секунды с начала эпохи


Ах, это объясняет много временных меток, которые я видел в Linux сейчас! Большое спасибо
Тим Александр

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.
10

3

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

Так как вы используете оболочку echo -e, и в любом случае у вас есть bash в строке shebang, вы можете использовать IFS=$'\n\b'. Сделать Backspace разделителем довольно странно. Вам все равно не нужно 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].pdf, A1.pdfи A2.pdfвы в конечном итоге A1.pdf A2.pdf A1.pdf A2.pdf. Вы можете отключить глобализацию с помощью set -f(и снова включить set +f), но здесь (как и в большинстве случаев) правильный путь - не использовать подстановку команд.

Используйте -execаргумент для find(или, если ваша система имеет -print0, вы можете использовать find … -print0 | xargs -0 …вместо этого; это полезно только для одновременного действия с несколькими файлами, если вам нужна переносимость в древние системы Linux или в существующие системы 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"' {} \;

0

По какой-то причине я пропустил ответ о touch -r; если по какой-то странной причине у вас нет GNU coreutils, statкак в принятом ответе, и вы не можете его использовать 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 (в секундах). Символ @ from coreutils преобразует его в iso-дату, которая dateможет понимать и переформатировать с помощью YYYYMMDDHHmm.SS, чтобы ее touchможно было понять. Я поместил dateкоманду в $ (), как эквивалент инвертированных тиков, поскольку они не могут быть повторно использованы в одной команде.


(1) Это, кажется, почти точно так же, как ответ Николаса Райли, но более сложный. Почему кто-то хотел бы использовать это, а не это (или, еще лучше, ответ Гленна Джекмана , используя touch -r)? (2)  stat можно положить в $(…); они могут быть использованы несколько раз в одной команде.
G-Man говорит: «Восстановите Монику»

Кроме его ответа с использованием времени модификации, а не времени создания, вы, похоже, правы. Я не заметил этот другой ответ. Вы можете проголосовать против меня.
Доминикз

Ну, если вы попросите меня, это не весело. :-) ⁠
G-Man говорит: «Восстановите Монику»
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.