Reputation: 295373
On Linux, one can run readlink /proc/self/fd/0
or readlink /dev/fd/0
to get the name of any file or device attached to stdin.
Is this possible on Mac OS?
To explain the use case -- I have a script which behaves roughly akin to the following:
IFS= read -r -d '' stdin_content ||:
for target; do
ssh "$target" "$command" < <(printf %s "$stdin_content")
done
This has obvious caveats when the content to be read contains literal NUL values (which can't be stored in scalar variables in shell), and with respect to losing position information within the input file; I'm willing to ignore those at the moment, or round-trip the $stdin
variable through base64 storage if need be.
It would be helpful if I could detect the case where the script's stdin were coming from a regular file, and directly redirect from that file within the loop. [ -f /dev/fd/0 ]
actually does do the right thing in bash on Mac OS, despite /dev/fd/0
not existing (the test
builtin is aware of the /dev/fd
extension), but I'm at a loss for a means to retrieve its name.
Upvotes: 4
Views: 734
Reputation: 40224
You can use the fcntl
function with the (BSD and Mac OS X specific) option F_GETPATH
:
$ cat stdinname.c
#include <stdio.h>
#include <fcntl.h>
int main() {
char path[80];
fcntl(0, F_GETPATH, path);
printf("stdin is `%s`\n", path);
}
$ gcc stdinname.c
$ ./a.out < stdinname.c
stdin is `/Users/eduffy/junk/stdinname.c`
The code should include some error checking .. but the gist of it is there.
Edit: Missed the bash
part. This seems to work .. not as nice as the /proc/self/...
approach:
lsof -p $$ | awk '{if($4=="0r"){print $9}}'
Edit 2: Here's a version that outputs the fields separated by the NULL byte for safer parsing.
lsof -p $$ -F fn0 | awk '-F\0' '{if($1=="f0"){print substr($2,2)}}'
Upvotes: 4