Charles Duffy
Charles Duffy

Reputation: 295373

Possible to get name of file attached to stdin in OS X?

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

Answers (1)

eduffy
eduffy

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

Related Questions