Use >&N
. It's portable and as you saw, actually works with sockets.
The only reason you would ever use /proc/self/fd
is you are running a program that expects a file name and can't be told to use an already open file descriptor. E.g. the <(cmd...)
redirection uses that, since almost all command line utilities can open a file pointed to by name, but not all support preopened file descriptors directly.
Your shell can use pre-existing file descriptors, though, so no need to go through /proc
.
Also, /proc/NNN/fd/
is specific to Linux, and requires that you have a mounted /proc
. On my Linux boxes, /dev/stdout
, /dev/fd/*
and others are symlinks to /proc/self/fd/*
etc., so they require /proc
too. On other Unixes, they might be different. According to the answers to an older question /dev/stdout
are specifically listed as outside POSIX.
As for why the redirection doesn't work as you tried: Trying out with strace
, the difference between the two is that for a >&N
redirection, bash
calls dup()
on the file descriptor, and for >/proc/self/fd/N
it just tries to open it as an ordinary file with open()
. Apparently proc
doesn't support opening new copies of sockets like that, so the call fails. Stream sockets are pretty much point to point links, so prohibiting opening of a new copy doesn't seem too unnatural. But why it works for pipes or with a dup
, I couldn't tell.
$ ls -l /proc/self/fd/3
lrwx------ 1 itvirta itvirta 64 Jul 14 18:24 /proc/self/fd/3 -> socket:[168157]
$ strace bash -c "echo foo >>/proc/self/fd/3" 2>&1 | grep open.*proc/self
open("/proc/self/fd/3", O_WRONLY|O_CREAT|O_APPEND, 0666) = -1 ENXIO (No such device or address)
Also this answer has some information about the portability of /proc/NNN/fd
This will give you the date in seconds (since the UNIX epoch)
date --date '2017-08-17 04:00:01' +%s # "1502938801"
And this will give you the date as a readable string from a number of seconds
date --date '@1502938801' # "17 Aug 2017 04:00:01"
So all that's needed is to convert your date/timestamp into a format that GNU date
can understand, use maths to determine the difference, and output the result
datetime1=20170817040001
datetime2=20160312000101
seconds1=$(date --date "$(echo "$datetime1" | sed -nr 's/(....)(..)(..)(..)(..)(..)/\1-\2-\3 \4:\5:\6/p')" +%s)
seconds2=$(date --date "$(echo "$datetime2" | sed -nr 's/(....)(..)(..)(..)(..)(..)/\1-\2-\3 \4:\5:\6/p')" +%s)
delta=$((seconds1 - seconds2))
echo "$delta seconds" # "45197940 seconds"
We've not provided timezone information here so it assumes local timezone. Your values for the seconds from the datetime will probably be different to mine. (If your values are UTC then you can use date --utc
.)
Best Answer
You can use the
date
utility to write the timestamp of afile
, and the current time, as seconds elapsed from the Epoch, then format a string to convert the seconds of the difference in days withbc
: