You can use an implication. In logic a -> b is translated as !a || b, thus:
DirInfo.EnumerateDirectories(".", SearchOption.AllDirectories)
.Where(x => !excludeSystem || (x.Attributes&FileAttributes.System) == 0);
.Where(x => !excludeHidden || (x.Attributes&FileAttributes.Hidden) == 0);
.Where(x => !excludeReadOnly || (x.Attributes&FileAttributes.ReadOnly) == 0);
Here we assume excludeSystem, excludeHidden and excludeReadOnly are bools that you first fetched from the checkboxes.
You can of course write it in one Where as well.
Explanation (one .Where):
Given the following expression
x => !excludeSystem || (x.Attributes&FileAttributes.System) == 0
You can read this as a predicate. Say excludeSystem is false, then !excludeSystem is true, thus all directories will succeed. If not, the the second operand (x.Attributes&FileAttributes.System) == 0 is executed.
The second operand first does and bitwise & on the Attributes of x and the constant FileAttributes.System. If the Attributes thus contain FileAttributes.System, the result will be something different than zero. In that case the second test fails. In other words, you return false if the files are excluded and the file is a system-file.
Optimize
In case you think you will iterate over thousands of directories, you can make the code a bit more efficient, by making the tests faster:
IEnumerable<DirectoryInfo> temp = DirInfo.EnumerateDirectories(".", SearchOption.AllDirectories);
if(excludeSystem) {
temp = temp.Where((x.Attributes&FileAttributes.System) == 0);
}
if(excludeHidden) {
temp = temp.Where((x.Attributes&FileAttributes.Hidden) == 0);
}
if(excludeReadOnly) {
temp = temp.Where((x.Attributes&FileAttributes.ReadOnly) == 0);
}
GetDirsToCopy = temp;
This will (almost) always be efficient, but it makes the code a bit less beautiful.