Find command is giving error on Mountain Lion

findosx-mountain-lion

I'm trying use the following command on Mac OSX Mountain Lion to get a list of my mail folders as part of my .muttrc file:

`echo -n "+ "; find ~/.mail/fastmail -maxdepth 1 -type d -name ".*" -printf "+'%f' "`
find: -printf: unknown primary or operator
-bash: +: command not found

How can I rewrite this to get the desired result?

Best Answer

OSX find has no -printf action. The +: command not found error is because your command is enclosed in back ticks (`` ), so the shell is treating the results of thefindcommand as a command and attempting to execute them, specifically it is trying to execute+` which is the first thing printed by the command you ran. You will get the same error if your run

`echo -n "+"` 

Back ticks are used to save the results of a command to a variable, so the above gives an error but this does not:

foo=`echo -n "+"`

You do not say what your desired output is. Based on your question, I assume you want to get a list of all folders in a given directory that start with a . and print their names on the same line, quoted and preceded by a +. If so, you can do something like this:

find ~/.mail/fastmail -maxdepth 1 -type d -name ".*"  -exec echo -n "+'{}' " \;

Sample output:

+'/home/terdon/.mail/fastmail/.bar' +'/home/terdon/.mail/fastmail/.foo' 

To pass the output of this command as input to another program (mailbox for example), do this:

mailbox `find ~/.mail/fastmail -maxdepth 1 -type d -name ".*"  -exec echo -n "+'{}' " \;`

or

mailbox $(find ~/.mail/fastmail -maxdepth 1 -type d -name ".*"  -exec echo -n "+'{}' " \;)

In response to OP's comment:

If you just want all folders, you don't need -name, to remove the quotes, just don't quote {}. I will also assume that you don't want the parent folder (fastmail), hence -mindpeth 1:

find ~/.mail/fastmail -maxdepth 1 -mindepth 1 -type d -exec echo -n "+{} " \;

Removing the path is slightly more complex because, contrary to what you might expect, you can't just use basename in the -exec call. You need to get creative, here are a few choices:

  • Parse with awk

    mailbox `find ~/.mail/fastmail -maxdepth 1 -mindepth 1 -type d | 
     awk -F"/" '{printf "+%s ",$NF}'`
    

    -F"/" tells awk to use / as the field delimiter and then print + followed by the last field ($NF) which will be the folder name.

  • Use a for loop (assuming that your folder names have no strange characters or spaces)

       mailbox `for dir in $(
         find ~/.mail/fastmail -maxdepth 1 -mindepth 1 -type d
        ); do echo -n "+$(basename $dir) "; done`
    

    If your folder names contain spaces or strange characters, use this instead:

    mailbox `find ~/.mail/fastmail -maxdepth 1 -mindepth 1 -type d | 
      while IFS= read -r dir; do echo -n "+$(basename $dir) "; done`
    
Related Question