It took me a few readings to figure out what you were really asking, but I think I finally have it now:
- We want to find added all or modified files (deleted files are probably irrelevant? type-change, from or to symbolic link, probably can't happen, etc).
- But, we want to toss out, from this list, any files that don't exist in a directory that itself contains or lives underneath a directory that contains a
*.csproj file.
That is, if the diff listing said that README.cs were updated in the top level, that would be irrelevant unless there were a top-level *.csproj file.
Now, we know that in general, the tool that will tell us which files are changed between any two individual commits is git diff (or for scripting purposes, git diff-tree). For instance, git diff parent child will tell us about the various files that are changed. Using --name-status gets us the path names and status letters.
Adding a diff filter for A and M, and making sure we control rename detection so that we either don't get R at all, or only get it for 100% matches, allows us to drop the "status" part, i.e, just --name-only. If we need to handle weird characters in file names, we can add -z and use \0 terminators with bash's read -r -d $'\0' construct (or -d ''; I like to write the explicit zero) as well.
Now, there's a general problem here: just because some *.cs file has changed doesn't mean the corresponding *.csproj file has also changed (well, presumably it doesn't). So we can't inspect the diff output for .csproj files. Unfortunately, to see whether there's a *.csproj file, the only direct tool we have here is git ls-tree -r --full-tree child, and it does not accept pathspec arguments, so we cannot ask about **/*.csproj for instance.
But there's a useful trick: valid *.csproj files are presumably always non-empty. Using git grep -l with the matching expression . will let us find such files. We can supply a commit hash ID here and then strip it from the output:
git grep -l --full-name . $hash -- "**/*.csproj" | sed "s/$hash://"
for instance.
Note that git grep is porcelain, like git diff, but it seems that -l defeats most of the options we'd have to worry about, and we want --full-name anyway here. To use git diff-tree, just add -r --no-commit-id. Rename detection is off in git diff-tree unless explicitly enabled.
That is, given the start and end commit hash IDs, or just HEAD:
git diff-tree -r --no-commit-id --name-only --diff-filter=AM HEAD -- "**/*.cs"
(If you use HEAD with git grep -l you'll want to strip a literal HEAD: from the output.)
Turning all this into a useful bash script will need a bit more work: you must run the git diff-tree, read its output, pick out the various directories, and compare with the git grep output's list of *.csproj-containing directories.
dotnet formathas an--includeoption to specify the files or folders that should be formatted. Did you consider this already? With this you could always run it against the whole solution but only include the modified & added files fromgit status.