Shell – “Touching” standard out

io-redirectionshell

This probably seems like a strange question, but say I have a script whose output is being written out to a file like so:

myscript.sh >> /path/to/some/file

Is it possible "touch" standard out such that the modification time of the output file can be updated without actually writing anything?

Obviously if the path were being passed directly into the script I could easily do this with the touch command, but that's not the case here, instead I'm redirecting standard out to a file.

So is there a clever way to touch the destination file when using I/O redirection, or do I need to handle the output path either internally, or inside some kind of wrapper script?

Best Answer

At least on Linux, /dev/stdout is a symlink in to /proc/self/fd/1, which is a symlink to the file — so touch /dev/stdout works:

user@host:~$ ( echo hi; stat -c '%y' /tmp/foo >&2; for i in 0 1 2; do sleep 2; touch /dev/stdout; stat -c '%y' /tmp/foo >&2; done ) >> /tmp/foo
2017-11-03 07:02:59.595622835 -0400
2017-11-03 07:03:01.599680859 -0400
2017-11-03 07:03:03.603738883 -0400
2017-11-03 07:03:05.611797023 -0400

On Linux, that succeeds or to does nothing silently when stdout is not a file (e.g., an anonymous pipe, e.g., ./myscript.sh | less, actually has an mtime and a socket's mtime is always 0). If stdout isn't open (which is possible, though rare), then it produces a diagnostic ("no such file or directory" on my machine). Same if stdout is to a non-writable file.

It's not at all portable, but will probably at worse produce a diagnostic and do nothing (at least as non-root, who shouldn't be able to write to /dev).

Depending on what your actual goal is, there is probably a better way. E.g., maybe you should pass the file name to the script, then it's trivial to use touch on it directly. Or if you're doing this to say "still alive!" maybe you want a separate file for that (or use a process supervisor and/or a pid file).

Related Question