user4184837
user4184837

Reputation:

How to get/set modification times in cross platform way from a (bash) script?

I use a combination of stat and touch for getting/setting timestamps on files and repertories. But I need different set-ups if on mac os x or GNU/Linux:

  1. touch on mac os x does not know the -d option described there

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

    which allows things like

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

    I am seemingly constrained to -t [[CC]YY]MMDDhhmm[.SS].

  2. stat also differs, for example on a Linux account of mine, it does not recognize the -t format from the stat on mac os x.

Thus on the Linux I currently do something like

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

to create a command line of the type

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

whereas on the mac os x I have

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

which gives me something (this is not the same index.html as prior) like:

touch -t 201503281339.42 "index.html"

How could handle this in a unified way ? Perhaps with some sed in between ?

I need to produce a sequence of touch commands in a format working on both platforms. The creation of this sequence must work on both platforms.

I am open to other scripting than bash, with the constraint that on the Linux side I am with a system with no admin rights. perl there is This is perl, v5.10.1 (*) built for x86_64-linux-thread-multi.

Upvotes: 1

Views: 432

Answers (2)

user4184837
user4184837

Reputation:

Short of a better method, I will temporarily adopt the following, which is based on these observations:

  1. touch -t works the same on my mac os x and the Linux I have access too.

  2. On the Linux side, I can use date -d to transform a date as produced by stat -c %y to the YYYYMMDDHHMM.SS format I can use on input to touch -t, and on the Mac OS X side I can use directly stat with suitable options for this result.

For batch processing of files in a repertory, where I was using stat with * shell expansion, I can replace that with a for shell loop.

Putting these things together I end with the following script:

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

Executing this in a repertory produces a file (with silly name here fichierTEMPA) which is a series of touch -t commands. The -h is for not following symbolic links, on mac os x, it implies the -c which is to not create a file which didn't exist, I am not sure if -c is also implied by -h on GNU/Linux.

Upvotes: 1

ceving
ceving

Reputation: 23826

Install the GNU Coreutils on your Mac and you can stop bothering about incompatibilities. It is explained here how to do it.

Upvotes: 0

Related Questions