Как получить/установить время модификации кросс-платформенным способом из сценария (bash)?

Я использую комбинацию stat и touch для получения/установки меток времени для файлов и реперториев. Но мне нужны разные настройки, если на mac os x или GNU/Linux:

  1. touch на mac os x не знает описанную там опцию -d

    http://pubs.opengroup.org/onlinepubs/9699919799/utilities/touch.html

    что позволяет такие вещи, как

    touch -d "2007-11-12 10:15:30.002Z" ajosey
    

    Кажется, я ограничен -t [[CC]YY]MMDDhhmm[.SS].

  2. stat также отличается, например, в моей учетной записи Linux он не распознает -t format от stat на mac os x.

Таким образом, в Linux я сейчас делаю что-то вроде

stat --format 'touch -d "%y" "%n"' index.html

создать командную строку типа

touch -d "2015-04-08 00:38:51.940365000 +0200" "index.html"

тогда как на mac os x у меня есть

stat -f "touch -t %Sm \"%N\"" -t %Y%m%d%H%M.%S index.html

что дает мне что-то (это не то же самое index.html, что и раньше), например:

touch -t 201503281339.42 "index.html"

Как можно было бы справиться с этим унифицированным способом? Возможно, с некоторым sed между ними?

Мне нужно создать последовательность touch команд в формате, работающем на обеих платформах. Создание этой последовательности должно работать на обеих платформах.

Я открыт для других сценариев, кроме bash, с тем ограничением, что на стороне Linux у меня есть система без прав администратора. perl есть This is perl, v5.10.1 (*) built for x86_64-linux-thread-multi.


person Community    schedule 02.02.2016    source источник
comment
Я думаю, вам просто нужно написать условный/переключатель на uname -o? (if [ $(uname -o) == linux ];then ....)   -  person Jeff Y    schedule 02.02.2016
comment
Вы можете отказаться от часового пояса. Он не будет записан в файловую систему: stackoverflow.com/questions/30119732/   -  person ceving    schedule 02.02.2016
comment
@JeffY Я надеялся на код, общий для GNU / Linux, такой как Ubuntu и Mac OS X ... сохраняя условное выражение в крайнем случае. И даже при использовании условных выражений мне нужно иметь возможность создать в Linux последовательность команд, подходящую для Mac OS, и наоборот.   -  person    schedule 02.02.2016
comment
@ceving хорошо, спасибо за ссылку, но это тоже не больно.   -  person    schedule 02.02.2016
comment
@jfbu Это больно, что это один пункт в списке несовместимостей: я, похоже, ограничен -t [[CC]YY]MMDDhhmm[.SS].   -  person ceving    schedule 02.02.2016
comment
@ceving, и это будет по местному времени, ты прав. Это означает, что мне нужен способ, если какая-то утилита возвращает время, чтобы либо запросить его без часового пояса, либо преобразовать его в местное время. Touch на mac os x принимает -A для применения дополнительного сдвига, например -A 010000 для сокращения на один час.   -  person    schedule 02.02.2016
comment
Использовать python вместо этого?   -  person trojanfoe    schedule 02.02.2016
comment
@trojanfoe подумает об этом, я надеюсь, что perl тоже подумает, но ему еще предстоит научиться.   -  person    schedule 02.02.2016
comment
Я так и ожидал, но это ужасный синтаксис...   -  person trojanfoe    schedule 02.02.2016
comment
@JeffY -o является недопустимым вариантом для uname в mac os x. Было бы больше похоже на uname -s: -s print the operating system name., что на практике возвращает Darwin. В моем Linux uname -s выводит Linux.   -  person    schedule 02.02.2016
comment
@JeffY Я дал самостоятельный ответ на основе условного переключения.   -  person    schedule 03.02.2016


Ответы (2)


За исключением лучшего метода, я временно приму следующий, основанный на этих наблюдениях:

  1. touch -t работает одинаково на моем Mac OS X и на Linux, к которому у меня есть доступ.

  2. На стороне Linux я могу использовать date -d для преобразования даты, созданной stat -c %y, в формат YYYYMMDDHHMM.SS, который я могу использовать при вводе в touch -t, а на стороне Mac OS X я могу использовать напрямую stat с подходящими параметрами для этого результата.

Для пакетной обработки файлов в реперториуме, где я использовал stat с расширением оболочки *, я могу заменить его циклом оболочки for.

Объединяя эти вещи, я заканчиваю следующим сценарием:

#!/bin/sh                                                                       
case `uname -s` in
    "Linux" )
        MYDATEFORTOUCH() {
            date -d"$(stat -c %y "$1")" +%Y%m%d%H%M.%S
        }
        ;;
    "Darwin" )
        MYDATEFORTOUCH() {
            stat -f %Sm -t %Y%m%d%H%M.%S "$1"
        }
        ;;
    * )
        MYDATEFORTOUCH() {
            197001010000.00
        }
        ;;
esac

echo "#!/bin/sh" > fichierTEMPA

for file in *
do echo "touch -ch -t $(MYDATEFORTOUCH "$file") \"$file\"" >> fichierTEMPA
done

Выполнение этого в реперториуме создает файл (с глупым именем здесь fichierTEMPA), который представляет собой серию touch -t команд. -h предназначен для того, чтобы не следовать символическим ссылкам, в mac os x он подразумевает -c, который должен не создавать несуществующий файл, я не уверен, что -c также подразумевается -h в GNU/Linux.

person Community    schedule 02.02.2016

Установите GNU Coreutils на свой Mac, и вы больше не будете беспокоиться о несовместимости. здесь объясняется, как это сделать.

person ceving    schedule 02.02.2016