Assuming you really do want a string, not a regexp, thus
fgrep -rl --null desired_string . | xargs -0 fgrep -lv undesired_string --
-r) grep for
desired_string under the current directory, printing the filenames (
-l) and using the filenames from that, repeatedly invoke fgrep (so as to not overfill the space for command-line arguments when invoking it), with
-v inverting the sense of the match.
--null to use an ASCII NUL character after each filename, instead of a newline, so that you can handle filenames with spaces in and the like; that plumbs into the
-0 given to xargs. Depending upon the Unix variant (Linux, BSD, etc) there might be a short option for
--null, but that's less portable. Strictly speaking,
--null is not portable, but any modern system's (f)grep should have it.
-- at the end of the second (f)grep stops (f)grep from looking for options in any following parameters, so even if you have a filename starting with a
-, it will still be processed as a filename.