understanding escaped parentheses in find

2019-08-08 14:17发布

I've cobbled together what is below, and it seems to work, with the possible exception of the "! -empty". One thing I'm learning (as I go) is that just because something works, doesn't mean it's right or formed correctly...The question I have is how do you determine what requires parentheses and what doesn't in a find command?

In OS X, -and is "implied by the juxtaposition of two expressions it does not have to be specified"

My goal is to have find: find directories that are over 5 minutes old, not empty, and are not .dot (hidden -i.e. "." and "..")

count="$( find . -type d -mmin +5 \! -empty \( ! -iname ".*" \) | wc -l )"
echo $count
if [ "$count" -gt 0 ] ; then
    echo $(date +"%r") "$cust_name loc 9: "${count}" directories exist to process, moving them" >> $logFILE
    find . -type d -mmin +5 \! -empty \( ! -iname ".*" \) | xargs -I % mv % ../02_processing/

    cd $processingPATH

    # append the time and the directories to be processed in files_sent.txt
    date +"---- %a-%b-%d %H:%M ----" >> $filesSENTlog
    ls >> $filesSENTlog

    find . -type f -print0 | xargs -0 /usr/local/dcm4che-2.0.28/bin/dcmsnd $aet@$peer:$port
    echo $(date +"%r") "$cust_name loc 10: Processing ${count} items..." >> $logFILE

    # clean up processed studies > from processing to processed
    echo $(date +"%r") "$cust_name loc 11: Moving ${count} items to 03_processed" >> $logFILE
    mv * $processedPATH
else
    echo $(date +"%r") "$cust_name loc 12: there are no directories to process" >> $logFILE
fi

could I just do:

find . -type d -mmin +5 \! -empty \! -iname ".*"

? or is that not correct for some reason?

1条回答
ゆ 、 Hurt°
2楼-- · 2019-08-08 15:22

find has the following operators listed in order of precedence (highest -> lowest)

  1. ()
  2. !|-not
  3. -a|-and
  4. -o|-or
  5. , (GNU only)

Note: All tests and actions have an implied -a linking each other

So if you are not using any operators, you don't have to worry about precedence. If you are just using not like in your case, you don't really have to worry about precedence either, since ! exp exp2 will get treated as (! exp) AND (exp2) as expected, due to ! having higher precedence than the implied and.

Example where precedence matters

> mkdir empty && cd empty && touch a && mkdir b
> find -mindepth 1 -type f -name 'a' -or -name 'b'
./a
./b

The above got treated as find -mindepth 1 (-type f AND -name 'a') OR (-name 'b')

> find -mindepth 1 -type f \( -name 'a' -or -name 'b' \)
./a

The above got treated as find -mindepth 1 (-type f) AND ( -name 'a' OR -name 'b')

Note: Options ( i.e. -mindepth, -noleaf, etc... ) are always true

Conclusion

The following two uses of find are exactly the same

  • find . -type d -mmin +5 \! -empty \( ! -iname ".*" \) | wc -l
  • find . -type d -mmin +5 \! -empty \! -iname ".*" | wc -l

Both get treated as

  • find . (-type d) AND (-mmin +5) AND (! -empty) AND (! -iname ".*") | wc -l
查看更多
登录 后发表回答