Como observado por @Arrow, com date implementações que suportam %N como as de GNU ou ast-open, você pode usar %s%3N para limitar a precisão, mas exceto em ksh93 onde date pode ser feito para ser a versão embutida do date do ast-open, o comando date não está embutido. Levará algumas centenas, senão mil microsegundos, para começar e mais alguns para imprimir a data e retornar.
bash copiou um subconjunto de ksh93 printf '%(...)T' format, mas não a %N part.
Aqui, parece que você precisa usar shells mais avançados, como ksh93 ou zsh .
Esses shells podem fazer com que sua variável $SECONDS registre o tempo desde que o shell iniciou (e que você também pode redefinir para qualquer valor) ponto flutuante:
$ typeset -F SECONDS=0; date +%s%3N; echo $SECONDS
1506318780647
0.0017870000
Demorou até 1787 microssegundos para executar o% GNUdate aqui.
Você pode usar $((SECONDS*1000)) para obter um número de milissegundos, pois ambos os shells suportam aritmética de ponto flutuante (cuidado: ksh93 homenageia a marca decimal do local).
Para o tempo de época como um ponto flutuante, zsh tem $EPOCHREALTIME :
$ zmodload zsh/datetime
$ echo $EPOCHREALTIME
1506318947.2758708000
E ksh93 pode usar "$(printf '%(%s.%N)T' now)" (observe que a substituição de comando de ksh93 não separa processos nem usa pipes para builtins, portanto não é tão cara quanto em outras shells parecidas com Bourne).
Você também pode definir a variável $EPOCHREALTIME com:
$ EPOCHREALTIME.get() { .sh.value=$(printf "%(%s.%6N)T");
$ echo "$EPOCHREALTIME"
1506333341.962697
Para o registro de data e hora automático, você também pode usar set -o xtrace e $PS4 que imprime a hora atual. Em zsh :
$ zsh -c 'PS4="+%D{%s.%.}> "; set -x; sleep 1; date +%s.%N'
+1506332128.753> sleep 1
+1506332129.754> date +%s.%N
1506332129.755322928
Em ksh93:
$ ksh -c 'PS4="+\$(printf "%(%s.%3N)T")> "; set -x; sleep 1; date +%s.%N'
+1506332247.844> sleep 1
+1506332248.851> date +%s.%N
1506332248.853111699
Dependendo do seu caso de uso, você pode contar com moreutils do ts para a sua marcação de tempo:
$ (date +%s.%6N; date +%s.%6N) | ts %.s
1506319395.000080 1506319394.970619
1506319395.000141 1506319394.971972
( ts dá tempo para ler a linha da saída de date pelo pipe).
Ou para o tempo entre as linhas de saída:
$ (date +%s.%6N; date +%s.%6N) | ts -i %.s
0.000011 1506319496.806554
0.000071 1506319496.807907
Se você deseja ter o tempo necessário para executar um determinado comando (pipeline), também é possível usar a palavra-chave time , ajustando o formato com $TIMEFORMAT em bash :
$ TIMEFORMAT=%E; time date
Mon 25 Sep 09:51:41 BST 2017
0.002
Essas diretivas de formato de hora vêm inicialmente de csh (embora bash , ao contrário de zsh ou GNU time , suporte apenas um subconjunto minúsculo). Em (t) csh, você pode cronometrar cada comando definindo a variável $time special:
$ csh -xc 'set time = (0 %E); sleep 1; sleep 2'
set time = ( 0 %E )
sleep 1
0:01.00
sleep 2
0:02.00
(o primeiro número ( 0 here) diz que os comandos que levam mais que muitos segundos devem ser cronometrados, o segundo especifica o formato).