Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding directories with find in bash using a exclude list

now before you think, "this has been done before" please read on.

Like most of the people trying to do a find bash script you end up hard-coding the script to a single line command, but end up editing the thing over the following months/years so often that you wish in the end you did it right the first time.

I am writing a little backup program right now to do backups of directories and need to find them, against a list of directorie's that needs to be excluded. Easier said than done. Let me set the stage:

#!/bin/bash
BasePath="/home/adesso/baldar"
declare -a Iggy
Iggy=( "/cgi-bin" 
    "/tmp" 
    "/test" 
    "/html" 
    "/icons" )
IggySubdomains=$(printf ",%s" "${Iggy[@]}")
IggySubdomains=${IggySubdomains:1}
echo $IggySubdomains
exit 0

Now at the end of this you get /cgi-bin,/tmp,/test,/html,/icons This proves that the concept works, but now to take it a bit further I need to use find to search the BasePath and search only one level deep for all subdirectories and exclude the list of subdirectories in the array...

If I type this by hand it would be:

find /var/www/* \( -path '*/cgi-bin' -o -path '*/tmp' -o -path '*/test' -o -path '*/html' -o -path '*/icons' \) -prune -type d

And should I maybe want to loop into each subdirectory and do the same... I hope you get my point.

So What I am trying to do seem possible, but I have a bit of a problem, printf ",%s" doesn't like me using all those find -path or -o options. Does this mean I have to use eval again?

I am trying to use the power of bash here, and not some for loop. Any constructive input would be appreciated.

like image 760
Adesso Avatar asked Nov 15 '11 16:11

Adesso


1 Answers

Try something like

find /var/www/* \( -path "${Iggy[0]}" $(printf -- '-o -path "*%s" ' "${Iggy[@]:1}") \) -prune -type d

and see what happens.

EDIT: added the leading * to each path as in your example.

And here's a complete solution based on your description.

#!/usr/bin/env bash
basepath="/home/adesso/baldar"
ignore=("/cgi-bin" "/tmp" "/test" "/html" "/icons")

find "${basepath}" -maxdepth 1 -not \( -path "*${ignore[0]}" $(printf -- '-o -path "*%s" ' "${ignore[@]:1}") \) -not -path "${basepath}" -type d

Subdirectories of $basepath excluding those listed in $ignore, presuming at least two in $ignore (fixing that is not hard).

like image 55
sorpigal Avatar answered Oct 13 '22 05:10

sorpigal