Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Why doesn't

find . -type f -exec echo $(file={}; echo ${file:0:5}) \;

give the first five characters of the file, while this works:

find . -type f -exec bash -c 'echo ${1:0:5}' funcname {} \;


I'm trying to batch convert a tree full of images to thumbnails, and I want to rename them on the fly by adding '_thumb' at the end of the filename but before the extension. This renaming process is easy for one file:

file='I am a picture.jpg'
mv \"$file\" \"${file%\.*}_thumb.${file##*\.}\"

(the second line expands to mv "I am a picture.jpg" "I am a picture_thumb.jpg")

but when I try to encapsulate this command in the -exec parameter of find(1) I cannot manipulate the filename given by find (examples simplified):

find . -type f -exec ${{}:0:5}) \;


bash: ${{}:0:5}: bad substitution

Using a subshell I get a bit further:

find . -type f -exec echo $(file={}; echo ${file:0:5}) \;

this does echo the filename, but does not execute the string manipulation for some reason.

I finally found the solution in this SO post:

find . -type f -exec bash -c 'echo ${1:0:5}' funcname {} \;

but I don't understand why this would work when the $(...) construct does not.

share|improve this question
up vote 5 down vote accepted

exec does what it says: uses exec(). It doesn't involve a shell unless it's told to (-exec bash ...), and if it did you would still need single quotes to keep your interactive shell from interpreting the variable interpolations. (The shell is not magic and does not know that you intended those to be interpolated by something else.)

For example, when you use the following command:

find . -type f -exec echo $(file={}; echo ${file:0:5}) \;

your shell first performs process substitution by executing $(file={}; echo ${file:0:5}), which simply outputs {}, then executes the final command:

find . -type f -exec echo {} \;
share|improve this answer
Ah, I see now. Of course ${file:0:5} returns {} if $file={}. When I use $(file={}; echo ${file:0:1}) it indeed outputs only {. – Tim Apr 9 '12 at 16:04

You must log in to answer this question.

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