4

I'm trying to get information about the types of all the files in a given directory tree. Running file * in the current directory works well enough, but it doesn't traverse into sub-directories and there doesn't seem to be an option to make it do so.

How exactly do I execute the file command recursively, so that it lists the file types of all the files in a given directory and its subdirectories?

2 Answers 2

13

The other answer provides not the best way:

find . -type f | file -f -

There are at least two problems:

  1. -f option is not required by POSIX, some implementations of file may not support it.
  2. find prints each path with a trailing newline character, so it's usually one path (file) per line. Then file -f - expects one path per line. The problem is with paths that contain newlines; they are still valid in Unix (yet uncommon). In the above approach such path will get to file in two or more lines and the tool will treat each line as a separate path to examine.

A robust and portable way:

find . -type f -exec file -- {} +

Notes:

  • -exec file {} \; would also work, but then a separate file would be invoked for every file found. With + file can get multiple operands (find is still able to call file multiple times if there are too many files to build a single command). Expect + to perform better. On the other hand file that processes multiple arguments may columnize its output, so it looks "better". Therefore the two versions (with + and with ;) may differ in formatting their outputs.
  • I used a double dash in case there's a file with name beginning with - that could be interpreted as an option. If the starting path is . (like in this case) many implementations of find will print paths starting with ., so -- is not necessary; but apparently not all implementations do this.
1

The words "all the files in a given directory and its subdirectories" should lean you toward the find command:

find . -type f | file -f -

Will recursively read all files from the current directory and sub directories and have file identify their type. You might want to add -z for types that include compression.

4
  • I suspected that, I was kinda just hoping there was an option to file that I was glossing over. It seems odd to create a tool advanced enough that it can uncompress archives to search but yet not provide a single option for recursive operation, and it's not what I've come to expect of UNIX-like tools. Oct 9, 2019 at 22:09
  • Also, is piping to file superior to using -exec? Oct 9, 2019 at 22:27
  • 1
    Yes, very. This version calls file once, exec calls it for every line, or every N lines. The forks and execs add up massively on a large operation.
    – davolfman
    Oct 10, 2019 at 16:22
  • Also, the old Unix philosophy is "A set of small sharp tools". Combining tools to perform a job is part of that, so tools are built to be combined. For example putting human-output on stderr so the useful output piped form stdout is easier to work with by the next tool in line. More recent GNU and Linux stuff may not follow that exactly.
    – davolfman
    Oct 10, 2019 at 16:26

You must log in to answer this question.

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