Identify File Types Reliably with mimetype
You will finish with a practical way to identify a file's MIME type, check its contents when the name is untrustworthy, and produce predictable output for a shell script. The examples use mimetype 0.34 from the Debian package libfile-mimeinfo-perl 0.34-1.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need a shell and a readable file. The normal checks are read-only and do not need sudo. This command consults the shared MIME-info database, so a missing or inaccessible database is an environment problem rather than a reason to guess from a filename.
1. Check one file in the normal mode
Run mimetype with the path you want to inspect:
$ mimetype /tmp/mimetype-sample.txt
/tmp/mimetype-sample.txt: text/plain
The default output includes the filename, a colon separator and the MIME type. The database can use both the name and the file's contents. The exact result depends on the installed shared MIME-info data, so compare the type with what the file is actually expected to contain.
Checkpoint: repeat the command with a real path, not the example path. If the command cannot read the file or the database, keep the error text for diagnosis rather than treating an empty result as a useful type.
2. Ignore a misleading extension
Use --magic-only when the suffix is not trustworthy. It disables checks based on extensions, globs and inode type, and examines content magic instead:
$ cp /tmp/mimetype-sample.txt /tmp/mimetype-sample.png
$ mimetype /tmp/mimetype-sample.png
/tmp/mimetype-sample.png: image/png
$ mimetype --magic-only /tmp/mimetype-sample.png
/tmp/mimetype-sample.png: text/plain
This example deliberately gives plain text a misleading .png name. The first result shows why a name-based match can be deceptive. The second is the content-based result. Copying the file creates temporary state, so remove these two example files when you have finished:
$ rm -- /tmp/mimetype-sample.txt /tmp/mimetype-sample.png
That cleanup is safe only for the example paths. Do not substitute a directory or a path you have not checked.
3. Choose a compact output form
For a script that only needs the type, --brief removes the filename:
$ mimetype --brief /path/to/input
text/plain
For a human-facing report, --describe prints the database description instead of the MIME type:
$ mimetype --describe /tmp/mimetype-sample.txt
/tmp/mimetype-sample.txt: Plain text document
Use --mimetype to select types explicitly. It is the default unless file compatibility mode is active. A custom separator is useful when another program consumes the filename and type as two fields:
$ mimetype --separator=' | ' /tmp/mimetype-sample.txt
/tmp/mimetype-sample.txt | text/plain
Notice that this output contains two spaces after the separator on this installed version. If you need a strict machine-readable format, use --output-format instead:
$ mimetype --output-format='%f|%m|%d' /tmp/mimetype-sample.txt
/tmp/mimetype-sample.txt|text/plain|Plain text document
The supported substitutions are %f for the filename, %m for the MIME type and %d for the description. Alignment is not available with this format, which is useful when you want to avoid parsing padding.
4. Inspect standard input
Use --stdin when the content arrives through a pipe rather than a path:
$ printf 'plain text\n' | mimetype --stdin
STDIN: text/plain
Standard-input detection uses magic typing only and is less powerful than checking a normal file. In particular, it cannot use the input's filename. The manpage also records an IO::Scalar dependency for this option; if your installation reports that the module is missing, repair the package installation or use a readable temporary file instead.
Do not pipe secrets into a diagnostic command on a shared system. The content is being inspected by a process, and a verbose or debug run may reveal details about how the result was reached.
5. Read many paths from a name file
Use --namefile when a list of paths already exists, with one name per line:
$ printf '%s\n' /path/to/first /path/to/second > /tmp/mimetype-names
$ mimetype --namefile /tmp/mimetype-names
/path/to/first: text/plain
/path/to/second: application/octet-stream
The names from that file are read before any paths written directly on the command line. Treat the list as data, not shell syntax: mimetype does not expand wildcards inside it. Delete the temporary list after checking it if it contains private paths:
$ rm -- /tmp/mimetype-names
6. Handle links, descriptions and failures
A symbolic link is classified as a link by default. Add --dereference to follow it and inspect its target:
$ ln -s /path/to/input /tmp/mimetype-link
$ mimetype /tmp/mimetype-link
/tmp/mimetype-link: inode/symlink
$ mimetype --dereference /tmp/mimetype-link
/tmp/mimetype-link: text/plain
$ rm -- /tmp/mimetype-link
Following a link reads the target, so check the target path before using this option on untrusted input. It does not modify either path.
An empty type or description usually means that the file does not exist, its name matched no known glob, or no description is available in the requested language. The command is also documented to return a non-zero status for command-line errors, missing dependencies or an inaccessible database. Verify a status immediately after the command:
$ mimetype --magic-only /path/to/input
$ status=$?
$ printf 'mimetype exit status: %s\n' "$status"
If you need to understand a surprising result, add --debug. Debug output is for investigation, not for a stable parser. Use --language=CODE with a two-letter language code when you need a localised description, and remember that an unavailable translation can produce an empty description.
Done means
- You can identify a normal file and recognise the filename-plus-type output.
- You can use
--magic-onlywhen an extension may be false. - You can select brief, descriptive or explicitly formatted output for the consumer.
- You know that standard input uses content magic and cannot use a filename.
- You can follow a symbolic link deliberately and check the command status immediately.