List directory name (only once) after multiple file extensions found

Here is a simplified example of my problem. Say I have the following 3 sub-directories;

./folder1
A.txt
A.sh

./folder2
B.txt

./folder3
C.txt
C.sh

I would like to list the directory names which contain both '.txt' & '.sh' type extensions. I have came up with the following code;

find . -type f \( -name "*.txt" -o -name "*.sh" \) -exec ls -l {} \; | sed 's/[^/]*$//'
 

This produces the following output;

./folder1/ (e.g ./folder1/A.txt)
./folder1/ (e.g ./folder1/A.sh)
./folder3/ (e.g ./folder3/C.txt)
./folder3/ (e.g ./folder3/C.sh)

This is a list of each directory for each instance of '.txt' and '.sh'. What I really want is only;

./folder1/
./folder3/

Would be great if this could all be done in the same line of code (find command). This is probably straight forward but I just cant seem to get it.

Thanks in advance.

Maybe this:

find . -type f \( -name "*.txt" -o -name "*.sh" \) -printf "%h\n" | sort -u

thanks for the quick response. I tried your method but got '-printf is not a valid option'. I tried it using just 'print' and got 'There is a missing conjunction'

How about this one:

find . -type f \( -name "*.txt" -o -name "*.sh" \) -exec dirname {} \; | sort -u

starting with your code fragment:

find . -type f \( -name "*.txt" -o -name "*.sh" \) -exec dirname {} \;  | sort -u

Tried the code but it now just outputs all the subdirectories in the main directory, regardless of the search criteria.

No way! What the command does is:

# Gets the result of the command below:
find . -type f \( -name "*.txt" -o -name "*.sh" \)
# And execute a:
dirname "<output line>"

A more verbose example:

find . -type f \( -name "*.txt" -o -name "*.sh" \) | xargs -t -I {} dirname "{}"

just tested it again, it works! Think I may have been putting in a rogue character.
Thanks

---------- Post updated 11-11-11 at 10:39 AM ---------- Previous update was 10-11-11 at 05:13 PM ----------

Ah, think i've found why I'm having problems. When I use the following code;

find . -type f \( -name "*.txt" -o -name "*.sh" \)

I get the output;

./folder1/A.txt
./folder1/A.sh
./folder2/B.txt
./folder3/C.txt
./folder3/C.sh

When I use your code;

find . -type f \( -name "*.txt" -o -name "*.sh" \) -exec dirname {} \; | sort -u

I get the output;

./folder1
./folder2
./folder3

So i'm just getting all the directories. The desired output is as follows (to eliminate any directory which doesn't contain 1 instance of both file extensions ;

./folder1
./folder3

Sorry if I was unclear before. Your help is appreciated.

Check this one:

# find ./folder* -type f \( -name "*.txt" -o -name "*.sh" \) -exec dirname {} \; | uniq -c | egrep '([ ]+ 2 .*)'
      2 ./folder1
      2 ./folder3

The final parse I let it to you! =o)