I've always wondered this but never took the time to find out, so I'll do so now - how portable is the usage shown here of either /proc/$$/fd/$N or /dev/fd/$N? I understand POSIX guarantees /dev/null, /dev/tty, and /dev/console (though I only found that out the other day after reading the comments on this answer) but what about these others?

As far as I can tell they're pretty common, but in what systems can I not expect to find them? Why not? Is it more likely to find one than the other? Will they always exhibit like attributes?

I tend to use these devices pretty extensively in all manner of ways, and I'd like to know if there's a chance I'd come up short just trying.

Also the above questions should be understood to be only what I think I'd like to know, but, since I obviously have to ask in the first place, I may not know best in this regard and they should not be considered stringent requirements for an answer. Just clue me in if you can, please.

2 Answers 2


The /proc/PID/fd/NUM symlinks are quasi-universal on Linux, but they don't exist anywhere else (except on Cygwin which emulates them). /proc/PID/fd/NUM also exist on AIX and Solaris, but they aren't symlinks. Portably, to get information about open files, install lsof.

Unices with /proc/PID/fd


Under Linux, /proc/PID/fd/NUM is a slightly magic symbolic link to the file that the process with the ID PID has open on the file descriptor NUM. This link is magic in that, for example, it can be used to access the file even if the file is removed. The link will track the file through renames, too. /proc/self is a magic symbolic link which points to /proc/PID where PID is the process that accesses the link.

This feature is present on virtually all Linux systems. It's provided by the driver for the proc filesystem, which is technically optional but used for so many things (including making the ps work — it reads from /proc/PID) that it's almost never left out even on embedded systems.


Cygwin emulates Linux's /proc/PID/fd/NUM (for Cygwin processes) and /proc/self.

Solaris (since version 2.6), AIX

There are /proc/PID/fd entries for each file descriptor, but they appear as the same type as the opened file, so they provide no information about the path of the file. They do however report the same stat information as fstat would report to the process that has the file open, so it's possible to determine on which filesystem the file is located and its inode number. Directories appear as symbolic links, however they are magic symlinks which can only be followed, and readlink returns an empty string.

Under AIX, the procfiles command displays some information about a process's open files. Under Solaris, the pfiles command displays some information about a process's open files. This does not include the path to the file (on Solaris, it does since Solaris 10, see below).

Solaris (since version 10)

In addition to /proc/PID/fd/NUM, modern Solaris versions have /proc/PID/path/NUM which contains symbolic links similar to Linux's symlinks in /proc/PID/fd/NUM. The pfiles command shows information about a process's open files, including paths.


/proc/PID/fd is a text file which contains one record (line) per file descriptor opened by the process. The file name is not tracked there.


/proc/PID/ is a directory, but it doesn't contain any information about file descriptors.

Unices with /proc but no direct access to file descriptors

(Note: sometimes it's possible to obtain information about a process's open files by riffling through its memory image which is accessible under /proc. I don't count that as “direct access”.)

Unices where /proc/PID is a file

The proc filesystem itself started out in UNIX 8th edition, but with a different structure, and went through Plan 9 and back to some unices. I think that all operating systems with a /proc have an entry for each PID, but on many systems, it's a regular file, not a directory. The following systems have a /proc/PID which needs to be read with ioctl:

  • Solaris up to 2.5
  • OSF/1 now known as Tru64
  • IRIX (?)
  • SCO (?)


MINIX 3 has a procfs server which provides several Linux-like components including /proc/PID/ directories. However there is no /proc/PID/fd.


FreeBSD has /proc/PID/ directories, but they do not provide information about open file descriptors. (There is however /proc/PID/file which is similar to Linux's /proc/PID/exe, giving access to the executable through a symbolic link.)

FreeBSD's procfs is deprecated.

Unices without /proc

  • HP-UX
  • OpenBSD
  • NetBSD
  • Mac OS X

File descriptor information through other channels


The fuser command lists the processes that have a specified file open, or a file open on the specified mount point. This command is standard (available on all XSI-compliant systems, i.e. POSIX with the X/Open System Interface Extension).

You can't go from a process to file names with this utility.


Lsof stands for “list open files”. It is a third-party tool, available (but usually not part of the default installation) for most unix variants. Obtaining information about open files is very system-dependent, as the analysis above might have made you suspect. The lsof maintainer has done the work of combining it all under a single interface.

You can read the FAQ to see what kinds of difficulties lsof has to put up with. On most unices, obtaining information about the names of open files requires parsing kernel data structures. Quoting from FAQ 3.3 “Why doesn't lsof report full path names?”:

Lsof can't obtain path name components from the kernel name caches of the following dialects:

  • AIX

Only the Linux kernel records full path names in the structures it maintains about open files; instead, most kernels convert path names to device and node number doublets and use them for subsequent file references once files have been opened.

If you need to parse information from lsof's output, be sure to use the -F mode (one field per line), preferably the -F0 mode (null-delimited fields). To get information about a specific file descriptor of a specific process, use the -a option with -p PID and -d NUM, e.g. lsof -a -p 123 -d 0 -F0n.

/dev/fd/NUM for file descriptors of the current process

Many unix variants provide a way to for a process to access its open files via a file name: opening /dev/fd/NUM is equivalent to calling dup(NUM). These names are useful when a program wants a file name but you want to pass an already-open file (e.g. a pipe or socket); for example the shells that implement process substitution use them where available (using a temporary named pipe where /dev/fd is unavailable).

Where /dev/fd exists, there are also usually (always?) synonyms (sometimes symbolic links, sometimes hard links, sometimes magic files with equivalent properties) /dev/stdin = /dev/fd/0, /dev/stdout = /dev/fd/1, /dev/stderr = /dev/fd/2.

  • Under Linux, /dev/fd is a symbolic link to /proc/self/fd.
  • Under most unices (IRIX, OpenBSD, NetBSD, SCO, Solaris, …), the entries in /dev/fd are character devices. They usually appear whether the file descriptor is open or not, and entries may not be available for file descriptors above a certain number.
  • Under FreeBSD and OSX, the fdescfs filesystem provides a dynamic /dev/fd directory which follows the open descriptors of the calling process. A static /dev/fd is available if /dev/fd is not mounted.
  • Under OSF/1 (Tru64), /dev/fd is provided via fdfs.
  • There is no /dev/fd on AIX or HP-UX.
  • Your statements about Solaris are a little outdated. With Solaris releases less than 10 years old, the pfiles command shows the file descriptors path. It retrieves this information from the /proc/<pid>/path directory which you might also mention. See docs.oracle.com/cd/E19253-01/817-0547/esxiq/index.html
    – jlliagre
    Commented Apr 8, 2014 at 23:00
  • how could a process know the fs path for one of its open file descriptors, so it could pass it as an argument while spawning another process? I imagine shells have to do this to implement "process substitution"
    – 0cd
    Commented Jan 30, 2023 at 23:26
  • @0cd There is no generic way to find a path for an open file descriptor. Sometimes the path doesn't exist (e.g. anonymous pipe or socket), sometimes it no longer exists (deleted file), sometimes the process doesn't have permission to see it. For process substitution, shells use /dev/fd on systems where it exists. That gives a named path to the file descriptor, not related to the original path through which the file descriptor was opened (if any). That path is simply /dev/fd/ followed by the fd in decimal, so the shell doesn't need any other knowledge, just the fd number. Commented Jan 31, 2023 at 10:42

The way /proc is implemented and the features it provides is not standardized in any way, see for instance here. According to Wikipedia, FreeBSD is "phasing out" /proc, see here for details .

As of /dev, /dev/fd/ is not part of POSIX or the Single User Specification (SUSv3) while System V and BSD support it.


Linux: /dev/fd/* are symlinks to /proc/self/fd.

FreeBSD: /dev/fd/* is provided through fdescfs.

NetBSD: same as FreeBSD.

OpenBSD: same as FreeBSD.

Solaris: has /dev/fd/*.

IRIX: has /dev/fd/*.

Tru64 Unix: has /dev/fd/* according to nixdoc.net, the genuine Tru64 documentation at HP is inscrutable (boy, what a mess! you find nothing!).

AIX: no indication found from publicly available documentation.

HP-UX: same as AIX.

  • So I'll find a /dev/fd/1 on a BSD that links to my current 1>? One thing i commonly do in linux is echo 'command' | . /dev/fd/0 - is this sort of thing likely to work across the board, do you think?
    – mikeserv
    Commented Apr 7, 2014 at 21:39
  • I haven't access to a BSD system right now, but that's how I understand it, yes. Commented Apr 7, 2014 at 22:54
  • 1
    If you ever find the time just to expand on that only a little more I'll accept this answer, i think, barring any surprise prof fd posts, that is. In any case the first article linked to was an enlightening read - thank you very much.
    – mikeserv
    Commented Apr 7, 2014 at 22:58
  • Yeah. I guess prof fd showed up after all, huh? So, better luck next time?
    – mikeserv
    Commented Apr 8, 2014 at 21:40
  • 1
    All right then. Linux: /dev/fd/* are symlinks to /proc/self/fd. FreeBSD: /dev/fd/* is provided through fdescfs. NetBSD: same as FreeBSD. OpenBSD: same as FreeBSD. Solaris: has /dev/fd/*. IRIX: has /dev/fd/*. Tru64 Unix: has /dev/fd/* (according to nixdoc.net, the genuine Tru64 documentation at HP is inscrutable). AIX: no indication found from publicly available documentation. HP-UX: same as AIX. Commented Apr 8, 2014 at 22:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .