inotify(7)
๐ inotify(7) โ Miscellaneous Information Manual ๐
okay bestie, settle in, because this is the inotify page and it's a long one (we're doing it in parts, don't worry). this is the manual for inotify, the Linux thing that lets you watch filesystem events like a nosy queen with binoculars. ๐
โจ NAME โจ
inotify โ monitoring filesystem events. that's it. that's the whole vibe. it watches your files and tells you when stuff happens. iconic behavior honestly.
๐ธ DESCRIPTION ๐ธ
so. the inotify API gives you a whole mechanism for monitoring filesystem events. you can use it to watch individual files, OR you can watch directories. and when you're watching a directory, inotify will hit you up with events for the directory itself and for the files inside that directory. package deal. ๐
here are the system calls that go with this API, and yes you need to know all of them:
inotify_init(2)creates an inotify instance and returns a file descriptor referring to that inotify instance. and then there's the more recentinotify_init1(2), which is literally likeinotify_init(2)but it has a flags argument that unlocks some extra functionality. glow-up. โจinotify_add_watch(2)manipulates the "watch list" that's associated with an inotify instance. every item in that watch list (we call each item a "watch") specifies the pathname of a file or directory, plus some set of events that the kernel should monitor for the file that pathname points to.inotify_add_watch(2)either creates a brand-new watch item or modifies one that already exists. and bestie, every watch has a unique "watch descriptor" โ that's an integer returned byinotify_add_watch(2)when the watch gets created. it's like the watch's little ID card. ๐ชช- when events happen for monitored files and directories, those events get made available to your application as structured data that you can read from the inotify file descriptor using
read(2)(more on that below). inotify_rm_watch(2)removes an item from an inotify watch list. bye girl. ๐- when all file descriptors referring to an inotify instance have been closed (using
close(2)), the underlying object and its resources are freed for reuse by the kernel, and all associated watches are automatically freed. it's giving spring cleaning.
with careful programming, an application can use inotify to efficiently monitor and cache the state of a set of filesystem objects. however โ and this is important, no cap โ robust applications should allow for the fact that bugs in the monitoring logic, or races of the kind described below, may leave the cache inconsistent with the filesystem state. so it's probably wise to do some consistency checking, and rebuild the cache whenever you detect inconsistencies. think of it as checking your reflection before you post. ๐ช
๐ Reading events from an inotify file descriptor
to figure out what events have actually occurred, an application read(2)s from the inotify file descriptor. if no events have occurred so far, then (assuming a blocking file descriptor) read(2) will just block until at least one event occurs โ unless it gets interrupted by a signal, in which case the call fails with the error EINTR; see signal(7). rude, but okay.
each successful read(2) returns a buffer containing one or more of the following structures:
struct inotify_event {
int wd; /* Watch descriptor */
uint32_t mask; /* Mask describing event */
uint32_t cookie; /* Unique cookie associating related
events (for rename(2)) */
uint32_t len; /* Size of name field */
char name[]; /* Optional null-terminated name */
};
let's break down the girls one by one:
wdidentifies the watch this event is for. it's one of the watch descriptors returned by a previous call toinotify_add_watch(2).maskcontains bits that describe the event that occurred (see below, we get there).cookieis a unique integer that connects related events. currently, this is only used for rename events โ it lets the resulting pair ofIN_MOVED_FROMandIN_MOVED_TOevents be connected by the application. for all other event types,cookieis set to0. so it's basically a little friendship bracelet linking two events together. ๐ซถ- the
namefield is present only when an event is returned for a file inside a watched directory; it identifies the filename within the watched directory. this filename is null-terminated, and it may include further null bytes ('\0') to align subsequent reads to a suitable address boundary. yes, alignment padding. she's doing her best. - the
lenfield counts all of the bytes inname, including the null bytes. so the size of eachinotify_eventstructure is thussizeof(struct inotify_event) + event.len.
the behavior when the buffer you hand to read(2) is too small to return information about the next event depends on your kernel version: before Linux 2.6.21, read(2) returns 0; since Linux 2.6.21, read(2) fails with the error EINVAL. specifying a buffer of size
sizeof(struct inotify_event) + NAME_MAX + 1
will be sufficient to read at least one event. write that down. ๐
๐ inotify events
the inotify_add_watch(2) mask argument, and the mask field of the inotify_event structure returned when read(2)ing an inotify file descriptor, are both bit masks identifying inotify events. the following bits can be specified in mask when calling inotify_add_watch(2) and may be returned in the mask field returned by read(2):
IN_ACCESS(+) File was accessed (e.g.,read(2),execve(2)).IN_ATTRIB(*) Metadata changed โ for example, permissions (e.g.,chmod(2)), timestamps (e.g.,utimensat(2)), extended attributes (setxattr(2)), link count (since Linux 2.6.25; e.g., for the target oflink(2)and forunlink(2)), and user/group ID (e.g.,chown(2)). basically the file got a makeover. ๐IN_CLOSE_WRITE(+) File opened for writing was closed.IN_CLOSE_NOWRITE(*) File or directory not opened for writing was closed.IN_CREATE(+) File/directory created in watched directory (e.g.,open(2)O_CREAT,mkdir(2),link(2),symlink(2),bind(2)on a UNIX domain socket).IN_DELETE(+) File/directory deleted from watched directory.IN_DELETE_SELFWatched file/directory was itself deleted. (this event also occurs if an object is moved to another filesystem, sincemv(1)in effect copies the file to the other filesystem and then deletes it from the original filesystem.) in addition, anIN_IGNOREDevent will subsequently be generated for the watch descriptor.IN_MODIFY(+) File was modified (e.g.,write(2),truncate(2)).IN_MOVE_SELFWatched file/directory was itself moved.IN_MOVED_FROM(+) Generated for the directory containing the old filename when a file is renamed.IN_MOVED_TO(+) Generated for the directory containing the new filename when a file is renamed.IN_OPEN(*) File or directory was opened.
inotify monitoring is inode-based: when monitoring a file (but not when monitoring the directory containing a file), an event can be generated for activity on any link to the file โ whether that's in the same directory or a different one. wild, right?
now. when monitoring a directory:
- the events marked above with an asterisk (
*) can occur both for the directory itself and for objects inside the directory; and - the events marked with a plus sign (
+) occur only for objects inside the directory (not for the directory itself).
Note: when monitoring a directory, events are not generated for the files inside the directory when the events are performed via a pathname (i.e., a link) that lies outside the monitored directory. iykyk.
when events are generated for objects inside a watched directory, the name field in the returned inotify_event structure identifies the name of the file within the directory.
the IN_ALL_EVENTS macro is defined as a bit mask of all of the above events. you can use this macro as the mask argument when calling inotify_add_watch(2). catch-all behavior, we love her. ๐
two additional convenience macros are defined:
IN_MOVE
Equates to IN_MOVED_FROM | IN_MOVED_TO.
IN_CLOSE
Equates to IN_CLOSE_WRITE | IN_CLOSE_NOWRITE.
the following further bits can be specified in mask when calling inotify_add_watch(2):
IN_DONT_FOLLOW(since Linux 2.6.15) Don't dereference pathname if it is a symbolic link. don't follow her, bestie, respect the boundary. ๐IN_EXCL_UNLINK(since Linux 2.6.36) By default, when watching events on the children of a directory, events are generated for children even after they have been unlinked from the directory. this can result in large numbers of uninteresting events for some applications (e.g., if watching/tmp, in which many applications create temporary files whose names are immediately unlinked). specifyingIN_EXCL_UNLINKchanges the default behavior, so that events are not generated for children after they have been unlinked from the watched directory.IN_MASK_ADDIf a watch instance already exists for the filesystem object corresponding to pathname, add (OR) the events in mask to the watch mask (instead of replacing the mask); the errorEINVALresults ifIN_MASK_CREATEis also specified. (yes, they fight. don't put both.)IN_ONESHOTMonitor the filesystem object corresponding to pathname for one event, then remove from watch list. one and done. main character exit. ๐ชIN_ONLYDIR(since Linux 2.6.15) Watch pathname only if it is a directory; the errorENOTDIRresults if pathname is not a directory. using this flag provides an application with a race-free way of ensuring that the monitored object is a directory. race-free?? slay.IN_MASK_CREATE(since Linux 4.18) Watch pathname only if it does not already have a watch associated with it; the errorEEXISTresults if pathname is already being watched.
using this flag provides an application with a way of ensuring that new watches do not modify existing ones. this is useful because multiple paths may refer to the same inode, and multiple calls to inotify_add_watch(2) without this flag may clobber existing watch masks. protect your watch masks, girl. ๐ก๏ธ
the following bits may be set in the mask field returned by read(2):
IN_IGNOREDWatch was removed explicitly (inotify_rm_watch(2)) or automatically (file was deleted, or filesystem was unmounted). see also BUGS.IN_ISDIRSubject of this event is a directory.IN_Q_OVERFLOWEvent queue overflowed (wdis-1for this event). ๐ญIN_UNMOUNTFilesystem containing watched object was unmounted. in addition, anIN_IGNOREDevent will subsequently be generated for the watch descriptor.
๐ง Examples
suppose an application is watching the directory dir and the file dir/myfile for all events. the examples below show some events that will be generated for these two objects. โจ
fd = open("dir/myfile", O_RDWR);
Generates IN_OPEN events for both dir and dir/myfile.
read(fd, buf, count);
Generates IN_ACCESS events for both dir and dir/myfile.
okay bestie, that's part 1 โ and there's more coming, so don't go anywhere. ๐ฆ stay tuned, we're only getting started. ๐
OK so picture it: dir is the vibe, dir/myfile is the moment, and here's what your fave syscalls be doing to them ๐
write(fd, buf, count);โ dropsIN_MODIFYevents for bothdiranddir/myfile. โจfchmod(fd, mode);โ dropsIN_ATTRIBevents for bothdiranddir/myfile. ๐close(fd);โ dropsIN_CLOSE_WRITEevents for bothdiranddir/myfile. ๐ฆ
Now say your app is watching the directories dir1 and dir2, plus the file dir1/myfile. Here's what shows up in the group chat:
link("dir1/myfile", "dir2/new");โ sparks anIN_ATTRIBevent formyfile๐ธ and anIN_CREATEevent fordir2.rename("dir1/myfile", "dir2/myfile");โ sparks anIN_MOVED_FROMevent fordir1, anIN_MOVED_TOevent fordir2, and anIN_MOVE_SELFevent formyfile. TheIN_MOVED_FROMandIN_MOVED_TOevents carry the samecookievalue, they're literally matching bestie bracelets. ๐
Okay next scenario: dir1/xx and dir2/yy are (the only) links to the same file, and an app is watching dir1, dir2, dir1/xx, and dir2/yy. Run these in order and this is what you get:
unlink("dir2/yy");โ sparks anIN_ATTRIBevent forxx(because its link count changed, not me getting emotional about it ๐ญ) and anIN_DELETEevent fordir2.unlink("dir1/xx");โ sparksIN_ATTRIB,IN_DELETE_SELF, andIN_IGNOREDevents forxx, plus anIN_DELETEevent fordir1.
And one more: say your app is watching the directory dir and (the empty) directory dir/subdir. Watch this:
mkdir("dir/new", mode);โ sparks anIN_CREATE | IN_ISDIRevent fordir. New folder energy ๐ฅrmdir("dir/subdir");โ sparksIN_DELETE_SELFandIN_IGNOREDevents forsubdir, plus anIN_DELETE | IN_ISDIRevent fordir. Gone but not forgotten ๐ซถ
๐ FILES ๐
/proc interfaces ๐ง
The set of watch descriptors being monitored via an inotify file descriptor? You can literally peek at them through the entry for that inotify file descriptor in the process's /proc/pid/fdinfo directory. See proc_pid_fdinfo(5) for the deets. ๐
๐ STANDARDS ๐
Linux. Periodt.
๐ HISTORY ๐
Linux 2.6.13,glibc 2.4.IN_DONT_FOLLOWIN_MASK_ADDIN_ONLYDIR
These three little icons? glibc 2.5, bestie. โญ
๐ญ NOTES ๐ญ
Inotify file descriptors can be monitored using select(2), poll(2), and epoll(7). When an event is ready, the file descriptor shows up as readable. โจ
Since Linux 2.6.25, signal-driven I/O notification is available for inotify file descriptors โ go read the discussion of F_SETFL (for setting the O_ASYNC flag), F_SETOWN, and F_SETSIG in fcntl(2). The siginfo_t structure (described over in sigaction(2)) that gets passed to the signal handler has these fields set:
si_fdis set to the inotify file descriptor number ๐ธsi_signois set to the signal numbersi_codeis set toPOLL_IN- and
POLLINis set insi_band.
If successive output inotify events produced on the inotify file descriptor are identical (same wd, mask, cookie, and name), they get coalesced into a single event if the older event hasn't been read yet (but see BUGS, bestie, we'll get there). This saves kernel memory for the event queue, but it also means an application can't use inotify to reliably count file events. Not that kind of girl. ๐
The events you get by reading from an inotify file descriptor form an ordered queue. So like, for example, it's guaranteed that when you rename from one directory to another, events are produced in the correct order on the inotify file descriptor. Queued up and polite about it. ๐
The FIONREAD ioctl(2) returns the number of bytes available to read from an inotify file descriptor. Free little byte count, no cap. ๐ข
โ ๏ธ CAVEATS โ ๏ธ
The inotify API gives you no information about the user or process that triggered the inotify event. In particular, there's no easy way for a process monitoring events via inotify to tell apart events it triggered itself from events other processes triggered. It's giving anonymous. ๐
Inotify only reports events that a user-space program triggers through the filesystem API. Which means it does not catch remote events happening on network filesystems. (Applications gotta fall back to polling the filesystem to catch those.) And also, various pseudo-filesystems such as /proc, /sys, and /dev/pts are not monitorable with inotify. Sorry bestie, no watch parties there. ๐ซ
The inotify API does not report file accesses and modifications that may occur because of mmap(2), msync(2), and munmap(2). Invisible to the algorithm.
The inotify API identifies affected files by filename. But by the time an application processes an inotify event, that filename may already have been deleted or renamed. Iconic and also chaotic. ๐ฆ
The inotify API identifies events via watch descriptors. It is the application's responsibility to cache a mapping (if one is even needed) between watch descriptors and pathnames. Heads up: directory renamings may affect multiple cached pathnames. So many pathnames. ๐ญ
Inotify monitoring of directories is not recursive โ to monitor subdirectories under a directory, you gotta create additional watches. For large directory trees this can take a significant amount of time. Manual labor fr fr. ๐
If you're monitoring an entire directory subtree and a new subdirectory gets created in that tree, or an existing directory gets renamed into that tree, be aware that by the time you create a watch for the new subdirectory, new files (and subdirectories) may already exist inside it. So you may want to scan the contents of the subdirectory immediately after adding the watch (and, if desired, recursively add watches for any subdirectories it contains). ๐ซถ
Note that the event queue can overflow. In this case, events are lost. Robust applications should handle the possibility of lost events gracefully. For example, it may be necessary to rebuild part or all of the application cache. (One simple, but possibly expensive, approach is to close the inotify file descriptor, empty the cache, create a new inotify file descriptor, and then re-create watches and cache entries for the objects to be monitored.)
If a filesystem is mounted on top of a monitored directory, no event is generated, and no events are generated for objects immediately under the new mount point. If the filesystem is subsequently unmounted, events will subsequently be generated for the directory and the objects it contains. Surprise! The vibes come back. ๐
๐ Dealing with rename() events ๐
As noted above, the IN_MOVED_FROM and IN_MOVED_TO event pair generated by rename(2) can be matched up via their shared cookie value. But the task of matching has some challenges. It's giving situationship. ๐
These two events are usually consecutive in the event stream you get when reading from the inotify file descriptor. However, this is not guaranteed. If multiple processes are triggering events for monitored objects, then (on rare occasions) an arbitrary number of other events may appear between the IN_MOVED_FROM and IN_MOVED_TO events. Furthermore, it is not guaranteed that the event pair is atomically inserted into the queue: there may be a brief interval where the IN_MOVED_FROM has appeared, but the IN_MOVED_TO has not. ๐
Matching up the IN_MOVED_FROM and IN_MOVED_TO event pair generated by rename(2) is thus inherently racy. (Don't forget that if an object is renamed outside of a monitored directory, there may not even be an IN_MOVED_TO event.) Heuristic approaches (e.g., assume the events are always consecutive) can be used to ensure a match in most cases, but will inevitably miss some cases, causing the application to perceive the IN_MOVED_FROM and IN_MOVED_TO events as being unrelated. If watch descriptors are destroyed and re-created as a result, then those watch descriptors will be inconsistent with the watch descriptors in any pending events. (Re-creating the inotify file descriptor and rebuilding the cache may be useful to deal with this scenario.) ๐ญ
Applications should also allow for the possibility that the IN_MOVED_FROM event was the last event that could fit in the buffer returned by the current call to read(2), and the accompanying IN_MOVED_TO event might be fetched only on the next read(2) โ which should be done with a (small) timeout to allow for the fact that insertion of the IN_MOVED_FROM+IN_MOVED_TO event pair is not atomic, and also the possibility that there may not be any IN_MOVED_TO event. Plan for the plot twist. ๐
๐ BUGS ๐
Before Linux 3.19, fallocate(2) did not create any inotify events. Since Linux 3.19, calls to fallocate(2) generate IN_MODIFY events. Glow up. โจ
Before Linux 2.6.16, the IN_ONESHOT mask flag does not work. Straight up broken, no cap.
As originally designed and implemented, the IN_ONESHOT flag did not cause an IN_IGNORED event to be generated when the watch was dropped after one event. However, as an unintended effect of other changes, since Linux 2.6.36, an IN_IGNORED event is generated in this case. Accidental icon behavior. ๐
Before Linux 2.6.25, the kernel code that was intended to coalesce successive identical events (i.e., the two most recent events could potentially be coalesced if the older had not yet been read) instead checked if the most recent event could be coalesced with the oldest unread event. Wrong event, bestie. ๐
When a watch descriptor is removed by calling inotify_rm_watch(2) (or because a watch file is deleted or the filesystem that contains it is unmounted), any pending unread events for that watch descriptor remain available to read. As watch descriptors are subsequently allocated with inotify_add_watch(2), the kernel cycles through the range of possible watch descriptors (1 to INT_MAX) incrementally. When allocating a free watch descriptor, no check is made to see whether that watch descriptor number has any pending unread events in the inotify queue. Thus, it can happen that a watch descriptor is reallocated even when pending unread events exist for a previous incarnation of that watch descriptor number, with the result that the application might then read those events and interpret them as belonging to the file associated with the newly recycled watch descriptor. ๐ป
In practice, the likelihood of hitting this bug may be extremely low, since it requires that an application cycle through INT_MAX watch descriptors, release a watch descriptor while leaving unread events for that watch descriptor in the queue, and then recycle that watch descriptor. For this reason, and because there have been no reports of the bug occurring in real-world applications, as of Linux 3.15, no kernel changes have yet been made to eliminate this possible bug. Lowkey cursed, highkey unfixed. ๐ญ
โจ EXAMPLES โจ
Okay bestie this is the part where it all comes together ๐ The program below is a whole demo of the inotify API in action โ it takes directories as command-line arguments, marks them, and then justโฆ waits ๐ specifically for events of type IN_OPEN, IN_CLOSE_NOWRITE, and IN_CLOSE_WRITE.
Here's what got recorded while someone was editing the file /home/user/temp/foo and listing the directory /tmp. Before the file and the directory got opened, IN_OPEN events popped off. After the file was closed, an IN_CLOSE_WRITE event showed up. After the directory was closed, an IN_CLOSE_NOWRITE event rolled in. And the whole program wrapped up the moment the user pressed the ENTER key. iconic behavior honestly ๐
๐ธ Example output ๐ธ
$ ./a.out /tmp /home/user/temp;
Press enter key to terminate.
Listening for events.
IN_OPEN: /home/user/temp/foo [file]
IN_CLOSE_WRITE: /home/user/temp/foo [file]
IN_OPEN: /tmp/ [directory]
IN_CLOSE_NOWRITE: /tmp/ [directory]
Listening for events stopped.
๐ฆ Program source ๐ฆ
no cap, here's the whole thing, every line, exactly as it is ๐
#include <errno.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include <unistd.h>
#include <string.h>
/* Read all available inotify events from the file descriptor 'fd'.
wd is the table of watch descriptors for the directories in argv.
argc is the size of wd and argv.
argv is the list of watched directories.
Entry 0 of wd and argv is unused. */
static void
handle_events(int fd, int *wd, int argc, char* argv[])
{
/* Some systems cannot read integer variables if they are not
properly aligned. On other systems, incorrect alignment may
decrease performance. Hence, the buffer used for reading from
the inotify file descriptor should have the same alignment as
struct inotify_event. */
char buf[4096]
__attribute__ ((aligned(__alignof__(struct inotify_event))));
const struct inotify_event *event;
ssize_t size;
/* Loop while events can be read from inotify file descriptor. */
for (;;) {
/* Read some events. */
size = read(fd, buf, sizeof(buf));
if (size == -1 && errno != EAGAIN) {
perror("read");
exit(EXIT_FAILURE);
}
/* If the nonblocking read() found no events to read, then
it returns -1 with errno set to EAGAIN. In that case,
we exit the loop. */
if (size <= 0)
break;
/* Loop over all events in the buffer. */
for (char *ptr = buf; ptr < buf + size;
ptr += sizeof(struct inotify_event) + event->len) {
event = (const struct inotify_event *) ptr;
/* Print event type. */
if (event->mask & IN_OPEN)
printf("IN_OPEN: ");
if (event->mask & IN_CLOSE_NOWRITE)
printf("IN_CLOSE_NOWRITE: ");
if (event->mask & IN_CLOSE_WRITE)
printf("IN_CLOSE_WRITE: ");
/* Print the name of the watched directory. */
for (size_t i = 1; i < argc; ++i) {
if (wd[i] == event->wd) {
printf("%s/", argv[i]);
break;
}
}
/* Print the name of the file. */
if (event->len)
printf("%s", event->name);
/* Print type of filesystem object. */
if (event->mask & IN_ISDIR)
printf(" [directory]\n");
else
printf(" [file]\n");
}
}
}
int
main(int argc, char* argv[])
{
char buf;
int fd, i, poll_num;
int *wd;
nfds_t nfds;
struct pollfd fds[2];
if (argc < 2) {
printf("Usage: %s PATH [PATH ...]\n", argv[0]);
exit(EXIT_FAILURE);
}
printf("Press ENTER key to terminate.\n");
/* Create the file descriptor for accessing the inotify API. */
fd = inotify_init1(IN_NONBLOCK);
if (fd == -1) {
perror("inotify_init1");
exit(EXIT_FAILURE);
}
/* Allocate memory for watch descriptors. */
wd = calloc(argc, sizeof(int));
if (wd == NULL) {
perror("calloc");
exit(EXIT_FAILURE);
}
/* Mark directories for events
- file was opened
- file was closed */
for (i = 1; i < argc; i++) {
wd[i] = inotify_add_watch(fd, argv[i],
IN_OPEN | IN_CLOSE);
if (wd[i] == -1) {
fprintf(stderr, "Cannot watch '%s': %s\n",
argv[i], strerror(errno));
exit(EXIT_FAILURE);
}
}
/* Prepare for polling. */
nfds = 2;
fds[0].fd = STDIN_FILENO; /* Console input */
fds[0].events = POLLIN;
fds[1].fd = fd; /* Inotify input */
fds[1].events = POLLIN;
/* Wait for events and/or terminal input. */
printf("Listening for events.\n");
for (;;) {
poll_num = poll(fds, nfds, -1);
if (poll_num == -1) {
if (errno == EINTR)
continue;
perror("poll");
exit(EXIT_FAILURE);
}
if (poll_num > 0) {
if (fds[0].revents & POLLIN) {
/* Console input is available. Empty stdin and quit. */
while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\n')
continue;
break;
}
if (fds[1].revents & POLLIN) {
/* Inotify events are available. */
handle_events(fd, wd, argc, argv);
}
}
}
printf("Listening for events stopped.\n");
/* Close inotify file descriptor. */
close(fd);
free(wd);
exit(EXIT_SUCCESS);
}
๐ SEE ALSO ๐
inotifywait(1)inotifywatch(1)inotify_add_watch(2)inotify_init(2)inotify_init1(2)inotify_rm_watch(2)read(2)stat(2)fanotify(7)
Also, if you wanna go deeper down the rabbit hole ๐ณ๏ธโจ there's Documentation/filesystems/inotify.rst chilling in the Linux kernel source tree.
๐ and that's a wrap on the whole page bestie!! this lil guy comes to you from Linux man-pages 6.20, dated 2026-09-11 ๐ go forth and watch some files, you absolute main character ๐๐๐
๐ฆ where this page comes from
- arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- ๐ the page's license: Linux-man-pages-copyleft
- Copyright 2006-2014, Michael Kerrisk <mtk.manpages@gmail.com>
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms