Why can I cat /dev?











up vote
38
down vote

favorite
4












I can cat /dev, I can ls /dev, I can't less /dev. Why does cat let me cat this directory but no other directories?



Picture of this behaviour in zsh.










share|improve this question









New contributor




haboutnnah is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • @KamilMaciorowski, here's the output and neofetch for your information :) i.imgur.com/3azpnDt.png
    – haboutnnah
    Nov 2 at 8:50

















up vote
38
down vote

favorite
4












I can cat /dev, I can ls /dev, I can't less /dev. Why does cat let me cat this directory but no other directories?



Picture of this behaviour in zsh.










share|improve this question









New contributor




haboutnnah is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • @KamilMaciorowski, here's the output and neofetch for your information :) i.imgur.com/3azpnDt.png
    – haboutnnah
    Nov 2 at 8:50















up vote
38
down vote

favorite
4









up vote
38
down vote

favorite
4






4





I can cat /dev, I can ls /dev, I can't less /dev. Why does cat let me cat this directory but no other directories?



Picture of this behaviour in zsh.










share|improve this question









New contributor




haboutnnah is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











I can cat /dev, I can ls /dev, I can't less /dev. Why does cat let me cat this directory but no other directories?



Picture of this behaviour in zsh.







macos cat






share|improve this question









New contributor




haboutnnah is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




haboutnnah is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited Nov 2 at 14:17









Filipe Brandenburger

2426




2426






New contributor




haboutnnah is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked Nov 2 at 7:01









haboutnnah

29636




29636




New contributor




haboutnnah is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





haboutnnah is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






haboutnnah is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












  • @KamilMaciorowski, here's the output and neofetch for your information :) i.imgur.com/3azpnDt.png
    – haboutnnah
    Nov 2 at 8:50




















  • @KamilMaciorowski, here's the output and neofetch for your information :) i.imgur.com/3azpnDt.png
    – haboutnnah
    Nov 2 at 8:50


















@KamilMaciorowski, here's the output and neofetch for your information :) i.imgur.com/3azpnDt.png
– haboutnnah
Nov 2 at 8:50






@KamilMaciorowski, here's the output and neofetch for your information :) i.imgur.com/3azpnDt.png
– haboutnnah
Nov 2 at 8:50












2 Answers
2






active

oldest

votes

















up vote
40
down vote



accepted










Historically (up to V7 UNIX, or around 1979) the read system call worked on both files and directories. read on a directory would return a simple data structure which a user program would parse to obtain the directory entries. Indeed, the V7 ls tool did exactly this - read on a directory, parse the resulting data structure, output in a structured list format.



As filesystems got more complex, this "simple" data structure got more complicated, to the point where a readdir library function was added to help programs parse the output of read(directory). Different systems and filesystems might have different on-disk formats, which was getting complicated.



When Sun introduced the Network File System (NFS), they wanted to fully abstract away the on-disk directory structure. Instead of making their read(directory) return a platform-independent representation of the directory, however, they added a new system call - getdirents - and banned read on network-mounted directories. This system call was rapidly adapted to work on all directories in various UNIX flavours, making it the default way to get the contents of the directories. (History abstracted from https://utcc.utoronto.ca/~cks/space/blog/unix/ReaddirHistory)



Because readdir is now the default way to read directories, read(directory) is usually not implemented (returning -EISDIR) on most modern OSes (QNX, for example, is a notable exception which implements readdir as read(directory)). However, with the "virtual filesystem" design in most modern kernels, it's actually up to the individual filesystem whether reading a directory works or not.



And indeed, on macOS, the devfs filesystem underlying the /dev mountpoint really does support reading (https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/bsd/miscfs/devfs/devfs_vnops.c#L629):



static int
devfs_read(struct vnop_read_args *ap)
{
devnode_t * dn_p = VTODN(ap->a_vp);

switch (ap->a_vp->v_type) {
case VDIR: {
dn_p->dn_access = 1;

return VNOP_READDIR(ap->a_vp, ap->a_uio, 0, NULL, NULL, ap->a_context);


This explicitly calls READDIR if you try to read /dev (reading files under /dev is handled by a separate function - devfsspec_read). So, if a program calls the read system call on /dev, it'll succeed and obtain a directory listing!



This is effectively a feature that is a holdover from the very early days of UNIX, and which hasn't been touched in a very long time. Part of me suspects that this is being kept around for some backwards compatibility reason, but it could just as easily be the fact that nobody cares enough to remove the feature since it isn't really hurting anything.






share|improve this answer





















  • Probably the latter, seeing as it has been removed from most directories.
    – user20574
    Nov 3 at 7:07


















up vote
36
down vote













Less is a text file viewer, cat is a tool for copying arbitrary data. So less performs its own checking to make sure you're not opening something that will have massive amounts of data or behave very strangely. On the other hand, cat has no such checking at all – if the kernel lets you open something (even if it's a pipe or a device or something worse), cat will read it.



So why does the OS allow cat to open directories? Traditionally in BSD-style systems all directories could be read as files, and that was how programs would list a directory in the first place: by just interpreting dirent structures stored on disk.



Later on, those on-disk structures began to diverge from the dirent used by the kernel: where previously a directory was a linear list, later filesystems began using hashtables, B-trees, and so on. So reading directories directly wasn't straightforward anymore – the kernel grew dedicated functions for this. (I'm not sure if that was the main reason, or if they were primarily added for other reasons such as caching.)



Some BSD systems continue to let you open all directories for reading; I don't know whether they give you the raw data from disk, or whether they return an emulated dirent list instead, or whether they let the filesystem driver decide.



So perhaps macOS is one of those operating systems where the kernel allows it as long as the filesystem provides the data. And the difference is that /dev is on a devfs filesystem that was written to allow this in the early days, while / is on an APFS filesystem that omitted this feature as unnecessary in modern times.



Disclaimer: I haven't actually done any research on BSDs or macOS. I'm just winging it.






share|improve this answer























  • This seems to make sense. Are there any other sections of storage that differ from the standard OS filesystem? I assumed /etc would, so I used that as my benchmark.
    – haboutnnah
    Nov 2 at 8:53








  • 2




    On the contrary, generally /etc is just a regular folder containing regular files. There may be other virtual filesystems though – run mount or /sbin/mount to see what's currently mounted where.
    – grawity
    Nov 2 at 8:58










  • You're right! See this: i.imgur.com/pcVpo1o.png
    – haboutnnah
    Nov 2 at 9:02










  • This is really neat @grawity, i.imgur.com/8QuR0FK.png
    – haboutnnah
    Nov 2 at 9:07






  • 6




    @haboutnnah Your screenshot confirms that /dev is a virtual file system using the devfs driver whereas /etc is part of the / file system using the apfs driver. So the reason cat will read one and not the other is a difference between the apfs and devfs drivers.
    – kasperd
    Nov 2 at 15:34











Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "3"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});






haboutnnah is a new contributor. Be nice, and check out our Code of Conduct.










 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsuperuser.com%2fquestions%2f1372086%2fwhy-can-i-cat-dev%23new-answer', 'question_page');
}
);

Post as a guest
































2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
40
down vote



accepted










Historically (up to V7 UNIX, or around 1979) the read system call worked on both files and directories. read on a directory would return a simple data structure which a user program would parse to obtain the directory entries. Indeed, the V7 ls tool did exactly this - read on a directory, parse the resulting data structure, output in a structured list format.



As filesystems got more complex, this "simple" data structure got more complicated, to the point where a readdir library function was added to help programs parse the output of read(directory). Different systems and filesystems might have different on-disk formats, which was getting complicated.



When Sun introduced the Network File System (NFS), they wanted to fully abstract away the on-disk directory structure. Instead of making their read(directory) return a platform-independent representation of the directory, however, they added a new system call - getdirents - and banned read on network-mounted directories. This system call was rapidly adapted to work on all directories in various UNIX flavours, making it the default way to get the contents of the directories. (History abstracted from https://utcc.utoronto.ca/~cks/space/blog/unix/ReaddirHistory)



Because readdir is now the default way to read directories, read(directory) is usually not implemented (returning -EISDIR) on most modern OSes (QNX, for example, is a notable exception which implements readdir as read(directory)). However, with the "virtual filesystem" design in most modern kernels, it's actually up to the individual filesystem whether reading a directory works or not.



And indeed, on macOS, the devfs filesystem underlying the /dev mountpoint really does support reading (https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/bsd/miscfs/devfs/devfs_vnops.c#L629):



static int
devfs_read(struct vnop_read_args *ap)
{
devnode_t * dn_p = VTODN(ap->a_vp);

switch (ap->a_vp->v_type) {
case VDIR: {
dn_p->dn_access = 1;

return VNOP_READDIR(ap->a_vp, ap->a_uio, 0, NULL, NULL, ap->a_context);


This explicitly calls READDIR if you try to read /dev (reading files under /dev is handled by a separate function - devfsspec_read). So, if a program calls the read system call on /dev, it'll succeed and obtain a directory listing!



This is effectively a feature that is a holdover from the very early days of UNIX, and which hasn't been touched in a very long time. Part of me suspects that this is being kept around for some backwards compatibility reason, but it could just as easily be the fact that nobody cares enough to remove the feature since it isn't really hurting anything.






share|improve this answer





















  • Probably the latter, seeing as it has been removed from most directories.
    – user20574
    Nov 3 at 7:07















up vote
40
down vote



accepted










Historically (up to V7 UNIX, or around 1979) the read system call worked on both files and directories. read on a directory would return a simple data structure which a user program would parse to obtain the directory entries. Indeed, the V7 ls tool did exactly this - read on a directory, parse the resulting data structure, output in a structured list format.



As filesystems got more complex, this "simple" data structure got more complicated, to the point where a readdir library function was added to help programs parse the output of read(directory). Different systems and filesystems might have different on-disk formats, which was getting complicated.



When Sun introduced the Network File System (NFS), they wanted to fully abstract away the on-disk directory structure. Instead of making their read(directory) return a platform-independent representation of the directory, however, they added a new system call - getdirents - and banned read on network-mounted directories. This system call was rapidly adapted to work on all directories in various UNIX flavours, making it the default way to get the contents of the directories. (History abstracted from https://utcc.utoronto.ca/~cks/space/blog/unix/ReaddirHistory)



Because readdir is now the default way to read directories, read(directory) is usually not implemented (returning -EISDIR) on most modern OSes (QNX, for example, is a notable exception which implements readdir as read(directory)). However, with the "virtual filesystem" design in most modern kernels, it's actually up to the individual filesystem whether reading a directory works or not.



And indeed, on macOS, the devfs filesystem underlying the /dev mountpoint really does support reading (https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/bsd/miscfs/devfs/devfs_vnops.c#L629):



static int
devfs_read(struct vnop_read_args *ap)
{
devnode_t * dn_p = VTODN(ap->a_vp);

switch (ap->a_vp->v_type) {
case VDIR: {
dn_p->dn_access = 1;

return VNOP_READDIR(ap->a_vp, ap->a_uio, 0, NULL, NULL, ap->a_context);


This explicitly calls READDIR if you try to read /dev (reading files under /dev is handled by a separate function - devfsspec_read). So, if a program calls the read system call on /dev, it'll succeed and obtain a directory listing!



This is effectively a feature that is a holdover from the very early days of UNIX, and which hasn't been touched in a very long time. Part of me suspects that this is being kept around for some backwards compatibility reason, but it could just as easily be the fact that nobody cares enough to remove the feature since it isn't really hurting anything.






share|improve this answer





















  • Probably the latter, seeing as it has been removed from most directories.
    – user20574
    Nov 3 at 7:07













up vote
40
down vote



accepted







up vote
40
down vote



accepted






Historically (up to V7 UNIX, or around 1979) the read system call worked on both files and directories. read on a directory would return a simple data structure which a user program would parse to obtain the directory entries. Indeed, the V7 ls tool did exactly this - read on a directory, parse the resulting data structure, output in a structured list format.



As filesystems got more complex, this "simple" data structure got more complicated, to the point where a readdir library function was added to help programs parse the output of read(directory). Different systems and filesystems might have different on-disk formats, which was getting complicated.



When Sun introduced the Network File System (NFS), they wanted to fully abstract away the on-disk directory structure. Instead of making their read(directory) return a platform-independent representation of the directory, however, they added a new system call - getdirents - and banned read on network-mounted directories. This system call was rapidly adapted to work on all directories in various UNIX flavours, making it the default way to get the contents of the directories. (History abstracted from https://utcc.utoronto.ca/~cks/space/blog/unix/ReaddirHistory)



Because readdir is now the default way to read directories, read(directory) is usually not implemented (returning -EISDIR) on most modern OSes (QNX, for example, is a notable exception which implements readdir as read(directory)). However, with the "virtual filesystem" design in most modern kernels, it's actually up to the individual filesystem whether reading a directory works or not.



And indeed, on macOS, the devfs filesystem underlying the /dev mountpoint really does support reading (https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/bsd/miscfs/devfs/devfs_vnops.c#L629):



static int
devfs_read(struct vnop_read_args *ap)
{
devnode_t * dn_p = VTODN(ap->a_vp);

switch (ap->a_vp->v_type) {
case VDIR: {
dn_p->dn_access = 1;

return VNOP_READDIR(ap->a_vp, ap->a_uio, 0, NULL, NULL, ap->a_context);


This explicitly calls READDIR if you try to read /dev (reading files under /dev is handled by a separate function - devfsspec_read). So, if a program calls the read system call on /dev, it'll succeed and obtain a directory listing!



This is effectively a feature that is a holdover from the very early days of UNIX, and which hasn't been touched in a very long time. Part of me suspects that this is being kept around for some backwards compatibility reason, but it could just as easily be the fact that nobody cares enough to remove the feature since it isn't really hurting anything.






share|improve this answer












Historically (up to V7 UNIX, or around 1979) the read system call worked on both files and directories. read on a directory would return a simple data structure which a user program would parse to obtain the directory entries. Indeed, the V7 ls tool did exactly this - read on a directory, parse the resulting data structure, output in a structured list format.



As filesystems got more complex, this "simple" data structure got more complicated, to the point where a readdir library function was added to help programs parse the output of read(directory). Different systems and filesystems might have different on-disk formats, which was getting complicated.



When Sun introduced the Network File System (NFS), they wanted to fully abstract away the on-disk directory structure. Instead of making their read(directory) return a platform-independent representation of the directory, however, they added a new system call - getdirents - and banned read on network-mounted directories. This system call was rapidly adapted to work on all directories in various UNIX flavours, making it the default way to get the contents of the directories. (History abstracted from https://utcc.utoronto.ca/~cks/space/blog/unix/ReaddirHistory)



Because readdir is now the default way to read directories, read(directory) is usually not implemented (returning -EISDIR) on most modern OSes (QNX, for example, is a notable exception which implements readdir as read(directory)). However, with the "virtual filesystem" design in most modern kernels, it's actually up to the individual filesystem whether reading a directory works or not.



And indeed, on macOS, the devfs filesystem underlying the /dev mountpoint really does support reading (https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/bsd/miscfs/devfs/devfs_vnops.c#L629):



static int
devfs_read(struct vnop_read_args *ap)
{
devnode_t * dn_p = VTODN(ap->a_vp);

switch (ap->a_vp->v_type) {
case VDIR: {
dn_p->dn_access = 1;

return VNOP_READDIR(ap->a_vp, ap->a_uio, 0, NULL, NULL, ap->a_context);


This explicitly calls READDIR if you try to read /dev (reading files under /dev is handled by a separate function - devfsspec_read). So, if a program calls the read system call on /dev, it'll succeed and obtain a directory listing!



This is effectively a feature that is a holdover from the very early days of UNIX, and which hasn't been touched in a very long time. Part of me suspects that this is being kept around for some backwards compatibility reason, but it could just as easily be the fact that nobody cares enough to remove the feature since it isn't really hurting anything.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 2 at 23:47









nneonneo

822612




822612












  • Probably the latter, seeing as it has been removed from most directories.
    – user20574
    Nov 3 at 7:07


















  • Probably the latter, seeing as it has been removed from most directories.
    – user20574
    Nov 3 at 7:07
















Probably the latter, seeing as it has been removed from most directories.
– user20574
Nov 3 at 7:07




Probably the latter, seeing as it has been removed from most directories.
– user20574
Nov 3 at 7:07












up vote
36
down vote













Less is a text file viewer, cat is a tool for copying arbitrary data. So less performs its own checking to make sure you're not opening something that will have massive amounts of data or behave very strangely. On the other hand, cat has no such checking at all – if the kernel lets you open something (even if it's a pipe or a device or something worse), cat will read it.



So why does the OS allow cat to open directories? Traditionally in BSD-style systems all directories could be read as files, and that was how programs would list a directory in the first place: by just interpreting dirent structures stored on disk.



Later on, those on-disk structures began to diverge from the dirent used by the kernel: where previously a directory was a linear list, later filesystems began using hashtables, B-trees, and so on. So reading directories directly wasn't straightforward anymore – the kernel grew dedicated functions for this. (I'm not sure if that was the main reason, or if they were primarily added for other reasons such as caching.)



Some BSD systems continue to let you open all directories for reading; I don't know whether they give you the raw data from disk, or whether they return an emulated dirent list instead, or whether they let the filesystem driver decide.



So perhaps macOS is one of those operating systems where the kernel allows it as long as the filesystem provides the data. And the difference is that /dev is on a devfs filesystem that was written to allow this in the early days, while / is on an APFS filesystem that omitted this feature as unnecessary in modern times.



Disclaimer: I haven't actually done any research on BSDs or macOS. I'm just winging it.






share|improve this answer























  • This seems to make sense. Are there any other sections of storage that differ from the standard OS filesystem? I assumed /etc would, so I used that as my benchmark.
    – haboutnnah
    Nov 2 at 8:53








  • 2




    On the contrary, generally /etc is just a regular folder containing regular files. There may be other virtual filesystems though – run mount or /sbin/mount to see what's currently mounted where.
    – grawity
    Nov 2 at 8:58










  • You're right! See this: i.imgur.com/pcVpo1o.png
    – haboutnnah
    Nov 2 at 9:02










  • This is really neat @grawity, i.imgur.com/8QuR0FK.png
    – haboutnnah
    Nov 2 at 9:07






  • 6




    @haboutnnah Your screenshot confirms that /dev is a virtual file system using the devfs driver whereas /etc is part of the / file system using the apfs driver. So the reason cat will read one and not the other is a difference between the apfs and devfs drivers.
    – kasperd
    Nov 2 at 15:34















up vote
36
down vote













Less is a text file viewer, cat is a tool for copying arbitrary data. So less performs its own checking to make sure you're not opening something that will have massive amounts of data or behave very strangely. On the other hand, cat has no such checking at all – if the kernel lets you open something (even if it's a pipe or a device or something worse), cat will read it.



So why does the OS allow cat to open directories? Traditionally in BSD-style systems all directories could be read as files, and that was how programs would list a directory in the first place: by just interpreting dirent structures stored on disk.



Later on, those on-disk structures began to diverge from the dirent used by the kernel: where previously a directory was a linear list, later filesystems began using hashtables, B-trees, and so on. So reading directories directly wasn't straightforward anymore – the kernel grew dedicated functions for this. (I'm not sure if that was the main reason, or if they were primarily added for other reasons such as caching.)



Some BSD systems continue to let you open all directories for reading; I don't know whether they give you the raw data from disk, or whether they return an emulated dirent list instead, or whether they let the filesystem driver decide.



So perhaps macOS is one of those operating systems where the kernel allows it as long as the filesystem provides the data. And the difference is that /dev is on a devfs filesystem that was written to allow this in the early days, while / is on an APFS filesystem that omitted this feature as unnecessary in modern times.



Disclaimer: I haven't actually done any research on BSDs or macOS. I'm just winging it.






share|improve this answer























  • This seems to make sense. Are there any other sections of storage that differ from the standard OS filesystem? I assumed /etc would, so I used that as my benchmark.
    – haboutnnah
    Nov 2 at 8:53








  • 2




    On the contrary, generally /etc is just a regular folder containing regular files. There may be other virtual filesystems though – run mount or /sbin/mount to see what's currently mounted where.
    – grawity
    Nov 2 at 8:58










  • You're right! See this: i.imgur.com/pcVpo1o.png
    – haboutnnah
    Nov 2 at 9:02










  • This is really neat @grawity, i.imgur.com/8QuR0FK.png
    – haboutnnah
    Nov 2 at 9:07






  • 6




    @haboutnnah Your screenshot confirms that /dev is a virtual file system using the devfs driver whereas /etc is part of the / file system using the apfs driver. So the reason cat will read one and not the other is a difference between the apfs and devfs drivers.
    – kasperd
    Nov 2 at 15:34













up vote
36
down vote










up vote
36
down vote









Less is a text file viewer, cat is a tool for copying arbitrary data. So less performs its own checking to make sure you're not opening something that will have massive amounts of data or behave very strangely. On the other hand, cat has no such checking at all – if the kernel lets you open something (even if it's a pipe or a device or something worse), cat will read it.



So why does the OS allow cat to open directories? Traditionally in BSD-style systems all directories could be read as files, and that was how programs would list a directory in the first place: by just interpreting dirent structures stored on disk.



Later on, those on-disk structures began to diverge from the dirent used by the kernel: where previously a directory was a linear list, later filesystems began using hashtables, B-trees, and so on. So reading directories directly wasn't straightforward anymore – the kernel grew dedicated functions for this. (I'm not sure if that was the main reason, or if they were primarily added for other reasons such as caching.)



Some BSD systems continue to let you open all directories for reading; I don't know whether they give you the raw data from disk, or whether they return an emulated dirent list instead, or whether they let the filesystem driver decide.



So perhaps macOS is one of those operating systems where the kernel allows it as long as the filesystem provides the data. And the difference is that /dev is on a devfs filesystem that was written to allow this in the early days, while / is on an APFS filesystem that omitted this feature as unnecessary in modern times.



Disclaimer: I haven't actually done any research on BSDs or macOS. I'm just winging it.






share|improve this answer














Less is a text file viewer, cat is a tool for copying arbitrary data. So less performs its own checking to make sure you're not opening something that will have massive amounts of data or behave very strangely. On the other hand, cat has no such checking at all – if the kernel lets you open something (even if it's a pipe or a device or something worse), cat will read it.



So why does the OS allow cat to open directories? Traditionally in BSD-style systems all directories could be read as files, and that was how programs would list a directory in the first place: by just interpreting dirent structures stored on disk.



Later on, those on-disk structures began to diverge from the dirent used by the kernel: where previously a directory was a linear list, later filesystems began using hashtables, B-trees, and so on. So reading directories directly wasn't straightforward anymore – the kernel grew dedicated functions for this. (I'm not sure if that was the main reason, or if they were primarily added for other reasons such as caching.)



Some BSD systems continue to let you open all directories for reading; I don't know whether they give you the raw data from disk, or whether they return an emulated dirent list instead, or whether they let the filesystem driver decide.



So perhaps macOS is one of those operating systems where the kernel allows it as long as the filesystem provides the data. And the difference is that /dev is on a devfs filesystem that was written to allow this in the early days, while / is on an APFS filesystem that omitted this feature as unnecessary in modern times.



Disclaimer: I haven't actually done any research on BSDs or macOS. I'm just winging it.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 2 at 18:41









Run5k

10.4k72749




10.4k72749










answered Nov 2 at 8:15









grawity

226k35469529




226k35469529












  • This seems to make sense. Are there any other sections of storage that differ from the standard OS filesystem? I assumed /etc would, so I used that as my benchmark.
    – haboutnnah
    Nov 2 at 8:53








  • 2




    On the contrary, generally /etc is just a regular folder containing regular files. There may be other virtual filesystems though – run mount or /sbin/mount to see what's currently mounted where.
    – grawity
    Nov 2 at 8:58










  • You're right! See this: i.imgur.com/pcVpo1o.png
    – haboutnnah
    Nov 2 at 9:02










  • This is really neat @grawity, i.imgur.com/8QuR0FK.png
    – haboutnnah
    Nov 2 at 9:07






  • 6




    @haboutnnah Your screenshot confirms that /dev is a virtual file system using the devfs driver whereas /etc is part of the / file system using the apfs driver. So the reason cat will read one and not the other is a difference between the apfs and devfs drivers.
    – kasperd
    Nov 2 at 15:34


















  • This seems to make sense. Are there any other sections of storage that differ from the standard OS filesystem? I assumed /etc would, so I used that as my benchmark.
    – haboutnnah
    Nov 2 at 8:53








  • 2




    On the contrary, generally /etc is just a regular folder containing regular files. There may be other virtual filesystems though – run mount or /sbin/mount to see what's currently mounted where.
    – grawity
    Nov 2 at 8:58










  • You're right! See this: i.imgur.com/pcVpo1o.png
    – haboutnnah
    Nov 2 at 9:02










  • This is really neat @grawity, i.imgur.com/8QuR0FK.png
    – haboutnnah
    Nov 2 at 9:07






  • 6




    @haboutnnah Your screenshot confirms that /dev is a virtual file system using the devfs driver whereas /etc is part of the / file system using the apfs driver. So the reason cat will read one and not the other is a difference between the apfs and devfs drivers.
    – kasperd
    Nov 2 at 15:34
















This seems to make sense. Are there any other sections of storage that differ from the standard OS filesystem? I assumed /etc would, so I used that as my benchmark.
– haboutnnah
Nov 2 at 8:53






This seems to make sense. Are there any other sections of storage that differ from the standard OS filesystem? I assumed /etc would, so I used that as my benchmark.
– haboutnnah
Nov 2 at 8:53






2




2




On the contrary, generally /etc is just a regular folder containing regular files. There may be other virtual filesystems though – run mount or /sbin/mount to see what's currently mounted where.
– grawity
Nov 2 at 8:58




On the contrary, generally /etc is just a regular folder containing regular files. There may be other virtual filesystems though – run mount or /sbin/mount to see what's currently mounted where.
– grawity
Nov 2 at 8:58












You're right! See this: i.imgur.com/pcVpo1o.png
– haboutnnah
Nov 2 at 9:02




You're right! See this: i.imgur.com/pcVpo1o.png
– haboutnnah
Nov 2 at 9:02












This is really neat @grawity, i.imgur.com/8QuR0FK.png
– haboutnnah
Nov 2 at 9:07




This is really neat @grawity, i.imgur.com/8QuR0FK.png
– haboutnnah
Nov 2 at 9:07




6




6




@haboutnnah Your screenshot confirms that /dev is a virtual file system using the devfs driver whereas /etc is part of the / file system using the apfs driver. So the reason cat will read one and not the other is a difference between the apfs and devfs drivers.
– kasperd
Nov 2 at 15:34




@haboutnnah Your screenshot confirms that /dev is a virtual file system using the devfs driver whereas /etc is part of the / file system using the apfs driver. So the reason cat will read one and not the other is a difference between the apfs and devfs drivers.
– kasperd
Nov 2 at 15:34










haboutnnah is a new contributor. Be nice, and check out our Code of Conduct.










 

draft saved


draft discarded


















haboutnnah is a new contributor. Be nice, and check out our Code of Conduct.













haboutnnah is a new contributor. Be nice, and check out our Code of Conduct.












haboutnnah is a new contributor. Be nice, and check out our Code of Conduct.















 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsuperuser.com%2fquestions%2f1372086%2fwhy-can-i-cat-dev%23new-answer', 'question_page');
}
);

Post as a guest




















































































這個網誌中的熱門文章

Xamarin.form Move up view when keyboard appear

Post-Redirect-Get with Spring WebFlux and Thymeleaf

Anylogic : not able to use stopDelay()