0

For some reason, when I try to check a file against FileAttributes.Normal, it seems like almost none of my files are showing up in my search. According to the API, that's because some other attributes are set. That's OK, I'll just need to search by what I don't want. This is where the problem comes in.

I'm incredibly rusty on my bitwise operator math, especially when it comes to checking multiple things at once. I'm trying to figure out how to get an if statement to return false if any of a certain number of file attributes are present (i.e. NONE of the specified attributes can be found if it wants to pass through my search). Here's what I've written so far:

if ((File.GetAttributes(stringFileName) &
   (FileAttributes.System | FileAttributes.Hidden | FileAttributes.Archive |
    FileAttributes.Encrypted | FileAttributes.Temporary)) == 0)

I'm thinking that it should take the conglomerate of all the different attributes and compare them to the original attributes of the file. If any match is found, the entire thing is rendered zero. However, this doesn't seem to be working as intended. Should I have used a different operator than the bitwise and (&)?

Thanks!

Update:

It appears that it wasn't the bitmask logic that was the problem, but rather FileAttributes.Archive. For some reason my files were nearly all marked with this flag (perhaps indicating that they are destined for backup?). At least now I know, and knowing is half the battle. :)

Mac Sigler
  • 189
  • 1
  • 15
  • As clarification, the design's intention is for the if statement to fail if any of the attributes are present. – Mac Sigler Jun 21 '12 at 15:33
  • If I comment out the if statement, it returns all the files (including the ones I want to hide). But for some reason, when I add in this if statement, almost no files show up. I'm thinking files are getting flagged something that they shouldn't be flagged with. – Mac Sigler Jun 21 '12 at 15:46
  • 'If any match is found, the entire thing is rendered zero.' This is not the case. If a file has any attribute that matches the ones you have specified, it will be NON-zero. – docmanhattan Jun 21 '12 at 15:50

3 Answers3

1

What this is doing is giving you just those attributes that you selected.

if ((File.GetAttributes(stringFileName) &
    (FileAttributes.System | FileAttributes.Hidden | FileAttributes.Archive |
    FileAttributes.Encrypted | FileAttributes.Temporary)) != 0)

There, just swap the equality for an inequality. This way, if any of those attributes are present, the final result will be non-zero.

TheZ
  • 3,663
  • 19
  • 34
  • Yes, but wouldn't I want the result to be zero if those attributes are present? I.e. the if statement fails if those attributes are present. – Mac Sigler Jun 21 '12 at 15:31
  • You said, "I'm trying to figure out how to get an if statement to return true if any of a certain number of file attributes are present." That is what this does. If any of the flags are set, it evaluates to true and the if statement runs. Your comment says you want the opposite. So, which is it? – TheZ Jun 21 '12 at 15:36
  • Definitely want it to return false if the attributes are present. Will edit my original post to clarify this. So it sounds like my code should already work then? Then I guess I have bigger problems than bitmasks. :( – Mac Sigler Jun 21 '12 at 15:42
  • It was the Archive flag after all. But thanks for spurring me on to check for that. – Mac Sigler Jun 21 '12 at 15:55
  • No problem, I'm glad you figured it out :) – TheZ Jun 22 '12 at 15:17
1

If you want the files with only the Normal attribute set then

if (File.GetAttributes(stringFileName) == FileAttributes.Normal)
    // True, file with only Normal attribute
else
    // False, file with some attributes but not the Normal one

According to MSDN FileAttributes.Normal means The file is normal and has no other attributes set. This attribute is valid only if used alone.

After some research I think that the problem lies in the Archive attribute. Would you like to test with this simple code?

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length != 1)
            {
                Console.WriteLine("Usage: CheckAllAtt <directoryName>");
                return;
            }
            var files = Directory.GetFiles(args[0]);
            foreach (string fileName in files)
            {
                FileAttributes att = File.GetAttributes(fileName);
                DumpAttr(fileName, att);
            }
        }
        private static void DumpAttr(string fileName, FileAttributes att)
        {
            StringBuilder sb = new StringBuilder("File: " + fileName);
            if ((att & FileAttributes.Archive) == FileAttributes.Archive)
                sb.Append(" Archive,");
            if ((att & FileAttributes.Compressed) == FileAttributes.Compressed)
                sb.Append(" Compressed,");
            if ((att & FileAttributes.Device) == FileAttributes.Device)
                sb.Append(" Device,");
            if ((att & FileAttributes.Directory) == FileAttributes.Directory)
                sb.Append(" Directory,");
            if ((att & FileAttributes.Encrypted) == FileAttributes.Encrypted)
                sb.Append(" Encrypted,");
            if ((att & FileAttributes.Hidden) == FileAttributes.Hidden)
                sb.Append(" Hidden,");
            if ((att & FileAttributes.Normal) == FileAttributes.Normal)
                sb.Append(" Normal,");
            if ((att & FileAttributes.NotContentIndexed) == FileAttributes.NotContentIndexed)
                sb.Append(" Normal,");
            if ((att & FileAttributes.Offline) == FileAttributes.Offline)
                sb.Append(" Offline,");
            if ((att & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                sb.Append(" ReadOnly,");
            if ((att & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint)
                sb.Append(" ReparsePoint,");
            if ((att & FileAttributes.SparseFile) == FileAttributes.SparseFile)
                sb.Append(" SparseFile,");
            if ((att & FileAttributes.System) == FileAttributes.System)
                sb.Append(" System,");
            if ((att & FileAttributes.Temporary) == FileAttributes.Temporary)
                sb.Append(" Temporary,");

            sb.Length -= 1;
            Console.WriteLine(sb.ToString());
        }
    }
}
Steve
  • 213,761
  • 22
  • 232
  • 286
  • It does seem like this should work, but as I've noted in my explanation above, it seems to filter out all my files. It must be that some obscure attribute is set, causing it not to be "Normal." This is why I decided to explicitly state which attributes I don't want to be shown. – Mac Sigler Jun 21 '12 at 15:29
  • Testing with a sample directory on my machine worked as expected, then switching to another directory where I execute regular backups turned out that the Archive atttribute ruined the simply test on FileAttributes.Normal. Added the code used to test a folder. – Steve Jun 21 '12 at 15:44
  • I too just independently realized it was the Archive attribute. But thanks for confirming my suspicions. – Mac Sigler Jun 21 '12 at 15:53
  • Exactly. Tried to reset the Archive attribute (attrib -a filename on dos window) restored the working of FileAttributes.Normal – Steve Jun 21 '12 at 16:01
0

Your logic is backwards. If any match is found then the result of bitwise and (&) is non-zero.

Examples:

A match: 0101000 & 0100000 = 0100000 != 0

No match: 0101000 & 0010000 = 0000000

zdan
  • 28,667
  • 7
  • 60
  • 71