tags:

views:

52

answers:

3

I would like to do something like:

find . -type f -exec test $(file --brief --mime-type '{}' ) == 'text/html' \; -print 

but I can't figure out the correct way to quote or escape the args to test, especially the '$(' ... ')' .

+5  A: 

You cannot simply escape the arguments for passing them to find.

Any shell expansion will happen before find is run. find will not pass its arguments through a shell, so even if you escape the shell expansion, everything will simply be treated as literal arguments to the test command, not expanded by the shell as you are expecting.

The best way to achieve what you want would be to write a short shell script, which takes the filename as an argument, and use -exec on that:

find . -type f -exec is_html.sh {} \; -print

with is_html.sh:

#!/bin/sh

test $(file --brief --mime-type "$1") == 'text/html'

If you really want it all on one line, without using a separate script, you can invoke sh directly from find:

find . -type f -exec sh -c 'test $(file --brief --mime-type "$0") == "text/html"' {} \; -print
Brian Campbell
I was afraid that would be the answer! I'm trying to avoid having to create a seperate command script just for the test. This seems to work as well: `find . -type f -exec file --mime-type '{}' \; | grep 'text/html' | cut -d':' -f1` , but I was hoping for a more general solution to this kind of pattern.
Steven D. Majewski
You can also use the -c option of bash instead of writing the code in a separate file: find . -type f -exec bash -c 'test $(file --brief --mime-type "$1") == "text/html"' '' {} \; -print
Bart Sas
@Bart yes, you can put it all inline by invoking `bash` or `sh` directly; I thought that it would be clearer to use a separate file, but you're right, if you really want to put it all on one line, you can do that.
Brian Campbell
+1 for explaining why my substitution can't work.
Steven D. Majewski
A: 

Although it may be possible to turn it into one wildly quoted statement, it is often easier - and more clear - to be a little more verbose:

$ find . -type f -print0 | xargs -0 file --mime-type | ↷
   grep ':[^:]*text/html$'| sed 's,:[^:]*text/html,,'
msw
A: 

Use "{}" instead, for an example this simply lists file types:

find * -maxdepth 0 -exec file "{}" \;