The "Everything is a file" phrase defines the architecture of the operating system. It means that everything in the system from processes, files, directories, sockets, pipes, ... is represented by a file descriptor abstracted over the virtual filesystem layer in the kernel. The virtual filesytem is an interface provided by the kernel. Hence the phrase was corrected to say "Everything is a file descriptor". Linus Torvalds himself corrected it again a bit more precisely: "Everything is a stream of bytes".
However, every "file" has also an owner and permissions you may know from regular files and directories. Therefore classic Unix tools like cat, ls, ps, ... can query all those "files" and it's not needed to invent other special mechanisms, than just the plain old tools, which all use the
read() system call. For example in Microsofts OS-family there are multiple different
read() system calls (I heard about 15) for any file types and every of them is a bit different. When everything is a file, then you don't need that.
To your question: Of course there are different file types. In linux there are 7 file types. The directory is one of them. But, the utilities can distinguish them from each other. For example, the complete function of the
cd command (when you press TAB) only lists directories, because the
stat() system call (see
man 2 stat) returns a struct with a field called
st_mode. The POSIX standard defines what that field can contain:
S_ISREG(m) is it a regular file?
S_ISCHR(m) character device?
S_ISBLK(m) block device?
S_ISFIFO(m) FIFO (named pipe)?
S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.)
S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
cd command completion function just displays "files" where the
S_ISDIR flag is set.