How to run the file command recursively

5,848

Solution 1

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.

Solution 2

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.

Share:
5,848

Related videos on Youtube

Hashim Aziz
Author by

Hashim Aziz

Updated on September 18, 2022

Comments

  • Hashim Aziz
    Hashim Aziz over 1 year

    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 an option to make it do so, which seems odd for a UNIX tool.

    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?

  • Hashim Aziz
    Hashim Aziz over 4 years
    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.
  • Hashim Aziz
    Hashim Aziz over 4 years
    Also, is piping to file superior to using -exec?
  • davolfman
    davolfman over 4 years
    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
    davolfman over 4 years
    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.