File system visiblilty

  • I use the following methods to get the visibility of files in the file
    system, but still some file some up in my list that do not show up in
    the Finder.  Any suggestions to get results more like the Finder gives?

    ...
    NSMutableArray *pathCont = [NSMutableArray arrayWithArray:[fileMan
    contentsOfDirectoryAtPath:path error:&fmErr]];
    if ([pathCont containsObject:@".hidden"]) {
      NSArray *hiddenList = [[NSString stringWithContentsOfFile: [path
      stringByAppendingPathComponent:@".hidden"]]
      componentsSeparatedByString: @"\n"];
      [pathCont removeObjectsInArray: hiddenList];
    }
    int i;
    for (i = 0; i < [pathCont count]; i++) {
      NSString *aFile = [pathCont objectAtIndex:i];
      if ([self isVisible:aFile])
      // code
    }
    ...

    - (BOOL)isVisible:(NSString *)path
    {
    if (([path hasPrefix:@"."]) || ([path characterAtIndex:([path length]
    - 1)] == 13)) return FALSE;

    OSStatus err;
        FSRef fileRef;
    Boolean isDirectory;
        err = FSPathMakeRef((UInt8 *)[path
    cStringUsingEncoding:NSASCIIStringEncoding], &fileRef,
    &isDirectory); // ? noErr : fnfErr;
        CFBooleanRef isInvisible;
        BOOL isVisible = YES;

        if (noErr == err)
            err = LSCopyItemAttribute(&fileRef, kLSRolesAll,
    kLSItemIsInvisible, (CFTypeRef *)&isInvisible);

        if (noErr == err) {
            isVisible = (CFBooleanGetValue(isInvisible) == FALSE);
            CFRelease(isInvisible);
        }
        return isVisible;
    }
  • First of all, filenames are not ASCII. They use
    fileSystemRepresentation.
    Second, what files in specific are you seeing which you shouldn't?
    And is "err" ever coming back as anything other than noErr? If so,
    what did you get?

    On Nov 14, 2007, at 4:52 PM, Justin Hawkwood wrote:

    > I use the following methods to get the visibility of files in the
    > file system, but still some file some up in my list that do not
    > show up in the Finder.  Any suggestions to get results more like
    > the Finder gives?
    >
    >
    >
    > ...
    > NSMutableArray *pathCont = [NSMutableArray arrayWithArray:[fileMan
    > contentsOfDirectoryAtPath:path error:&fmErr]];
    > if ([pathCont containsObject:@".hidden"]) {
    > NSArray *hiddenList = [[NSString stringWithContentsOfFile: [path
    > stringByAppendingPathComponent:@".hidden"]]
    > componentsSeparatedByString: @"\n"];
    > [pathCont removeObjectsInArray: hiddenList];
    > }
    > int i;
    > for (i = 0; i < [pathCont count]; i++) {
    > NSString *aFile = [pathCont objectAtIndex:i];
    > if ([self isVisible:aFile])
    > // code
    > }
    > ...
    >
    >
    > - (BOOL)isVisible:(NSString *)path
    > {
    > if (([path hasPrefix:@"."]) || ([path characterAtIndex:([path
    > length] - 1)] == 13)) return FALSE;
    >
    > OSStatus err;
    > FSRef fileRef;
    > Boolean isDirectory;
    > err = FSPathMakeRef((UInt8 *)[path
    > cStringUsingEncoding:NSASCIIStringEncoding], &fileRef,
    > &isDirectory); // ? noErr : fnfErr;
    > CFBooleanRef isInvisible;
    > BOOL isVisible = YES;
    >
    > if (noErr == err)
    > err = LSCopyItemAttribute(&fileRef, kLSRolesAll,
    > kLSItemIsInvisible, (CFTypeRef *)&isInvisible);
    >
    > if (noErr == err) {
    > isVisible = (CFBooleanGetValue(isInvisible) == FALSE);
    > CFRelease(isInvisible);
    > }
    > return isVisible;
    > }
  • On 15/11/2007, at 10:52 AM, Justin Hawkwood wrote:

    > I use the following methods to get the visibility of files in the
    > file system, but still some file some up in my list that do not show
    > up in the Finder.  Any suggestions to get results more like the
    > Finder gives?

    You're using LaunchServices which is the right way to do this, however
    you are not creating the FSRef properly. John is right, you shouldn't
    use NSASCIIStringEncoding as paths are definitely not ASCII. I use
    CFURLGetFSRef to create the FSRef which is much simpler.

    You also don't need to check for the period at the beginning of the
    file name etc because the Launch Services check does all that for you.

    I use code similar to this:

    -(BOOL)isVisible:(NSString *)path
    {
    //check to see if the file is visible by inspecting the
    LaunchServices attributes
    FSRef ref;
    if (CFURLGetFSRef((CFURLRef)[NSURL fileURLWithPath:path],&ref))
    {
      CFTypeRef isInvisible;
      if(LSCopyItemAttribute(&ref, kLSRolesAll, kLSItemIsInvisible, &
    isInvisible)==noErr)
      {
      if(isInvisible!=kCFBooleanTrue)
      {
        [visibleFolderContents addObject:currentFileName];
      }
      CFRelease(isInvisible);
      }
    }
    }

    --
    Rob Keniger
  • Sorry, in modifying my original routine for the email things got a bit
    munged, a more useful working routine is:

    -(BOOL)isVisible:(NSString *)path
    {
    BOOL isVisible=NO;
    //check to see if the file is invisible by checking the
    LaunchServices attributes
    FSRef ref;
    if (CFURLGetFSRef((CFURLRef)[NSURL fileURLWithPath:path],&ref))
    {
      CFTypeRef isInvisible;
      if(LSCopyItemAttribute(&ref, kLSRolesAll, kLSItemIsInvisible,
    &isInvisible)==noErr)
      {
      if(isInvisible!=kCFBooleanTrue)
      {
        isVisible=YES;
      }
      CFRelease(isInvisible);
      }
    }
    return isVisible;
    }

    --
    Rob Keniger
  • Thanks!  The missing "stringByAppendingPathComponent" made all the
    difference.  In fact, I no longer needed to check for [aFile
    hasPrefix:@"."]  as the rest of the function picks it up.  These
    changes, along with changing the cStringUsingEncoding: to
    NSUTF8StringEncoding, has picked up almost all of the remaining files/
    folders.  The only two that I see off the bat that are not turning
    invisible are /net and /home.

    Thanks all,

      Justin

    On Nov 14, 2007, at 5:25 PM, Chris Campbell wrote:

    > On Nov 14, 2007, at 7:52 PM, Justin Hawkwood wrote:
    >
    >> ...
    >> NSMutableArray *pathCont = [NSMutableArray arrayWithArray:[fileMan
    >> contentsOfDirectoryAtPath:path error:&fmErr]];
    >
    > Note that contentsOfDirectoryAtPath:error: will return an array of
    > file/directory names ("MyWordFile.doc", "YayPlainText.txt"), not
    > full paths ("/Users/chris/Documents/MyWordFile.doc", ...). So later
    > on, when you loop through it:
    >
    >
    >> int i;
    >> for (i = 0; i < [pathCont count]; i++) {
    >> NSString *aFile = [pathCont objectAtIndex:i];
    >> if ([self isVisible:aFile])
    >> // code
    >> }
    >
    > You should build a full path by concatenating the file/directory
    > name to the end of the containing directory's path:
    >
    > NSString *aFile = [path stringByAppendingPathComponent:[pathCont
    > objectAtIndex:i]];
    >
    > Knowing that, your logic in isVisible: would need to change:
    >
    >> - (BOOL)isVisible:(NSString *)path
    >> {
    >> if (([path hasPrefix:@"."]) || ([path characterAtIndex:([path
    >> length] - 1)] == 13)) return FALSE;
    >
    > You don't need to test if the full path starts with ".", you want to
    > test if the last component of the path starts with ".", like so:
    >
    > if (([[path lastPathComponent] hasPrefix:@"."]) || ...
    >
    > Have fun!
    >
    > - Chris
    >
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today