Файл скрыт? - PullRequest
       9

Файл скрыт?

4 голосов
/ 17 июля 2009

Как определить, указывает ли определенный путь на скрытый файл / папку?

NSString *file = @"/my/file/some.where";
BOOL fileIsHidden = // <-- what do I do here?

Я знаю, что скрытые файлы имеют префикс в виде точки. Это не единственный критерий скрытия файла. Я где-то читал, что есть скрытый файл, который также определяет, какие файлы скрыты.

Есть ли способ Какао / Карбон легко это выяснить, не переписывая всю эту логику и не собирая информацию из различных источников?

РЕДАКТИРОВАТЬ: проверка kLSItemInfoIsInvisible, кажется, работает для некоторых файлов. Кажется, это не скрывает:

/dev
/etc
/tmp
/var

Все они по умолчанию скрыты Finder.

Ответы [ 5 ]

5 голосов
/ 17 июля 2009

Как указывал автор, похоже, он не работает на / etc и / var, а на что нет, поэтому я изменил метод.

Теперь он принимает логическое значение isFile, YES означает его файл, NO означает каталог

BOOL isInvisible(NSString *str, BOOL isFile){
        CFURLRef inURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)str, kCFURLPOSIXPathStyle, isFile);
        LSItemInfoRecord itemInfo;
        LSCopyItemInfoForURL(inURL, kLSRequestAllFlags, &itemInfo);

        BOOL isInvisible = itemInfo.flags & kLSItemInfoIsInvisible;
        return (isInvisible != 0);
    }

    int main(){
           NSLog(@"%d",isInvisible(@"/etc",NO)); // => 1
           NSLog(@"%d",isInvisible(@"/Users",NO)); // => 0
           NSLog(@"%d",isInvisible(@"/mach_kernel",YES)); // => 1

    }

Кажется, теперь все работает!

4 голосов
/ 17 июля 2009

Насколько я знаю, скрытые файлы в OS X определяются либо именем файла с префиксом точки, либо специальным битом "невидимка", который отслеживается Finder.

Несколько лет назад мне пришлось написать что-то, что переключало видимость данного файла, и я обнаружил, что это на самом деле намного сложнее, чем я ожидал. Суть его в том, чтобы получить запись Finder info (FInfo) для файла и проверить, был ли установлен бит kIsInvisible. Вот метод, который я написал для переключения видимости файла - я думаю, что многое из этого имеет отношение к вашей задаче, хотя вам, очевидно, придется немного его настроить.

- (BOOL)toggleVisibilityForFile:(NSString *)filename isDirectory:(BOOL)isDirectory
{
    // Convert the pathname to HFS+
    FSRef fsRef;
    CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)filename, kCFURLPOSIXPathStyle, isDirectory);

    if (!url)
    {
        NSLog(@"Error creating CFURL for %@.", filename);
        return NO;
    }

    if (!CFURLGetFSRef(url, &fsRef))
    {
        NSLog(@"Error creating FSRef for %@.", filename);
        CFRelease(url);
        return NO;
    }

    CFRelease(url);

    // Get the file's catalog info
    FSCatalogInfo *catalogInfo = (FSCatalogInfo *)malloc(sizeof(FSCatalogInfo));
    OSErr err = FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, catalogInfo, NULL, NULL, NULL);

    if (err != noErr)
    {
        NSLog(@"Error getting catalog info for %@. The error returned was: %d", filename, err);
        free(catalogInfo);
        return NO;
    }

    // Extract the Finder info from the FSRef's catalog info
    FInfo *info = (FInfo *)(&catalogInfo->finderInfo[0]);

    // Toggle the invisibility flag
    if (info->fdFlags & kIsInvisible)
        info->fdFlags &= ~kIsInvisible;
    else
        info->fdFlags |= kIsInvisible;

    // Update the file's visibility
    err = FSSetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, catalogInfo);

    if (err != noErr)
    {
        NSLog(@"Error setting visibility bit for %@. The error returned was: %d", filename, err);
        free(catalogInfo);
        return NO;
    }

    free(catalogInfo);
    return YES;
}

Вот документация Apple по Finder Interface , если вам нужна дополнительная информация. Надеюсь, это поможет.

3 голосов
/ 17 июля 2009

С http://forums.macosxhints.com/archive/index.php/t-22641.html:

BOOL isInvisibleCFURL(CFURLRef inURL)
{
  LSItemInfoRecord itemInfo;
  LSCopyItemInfoForURL(inURL, kLSRequestAllFlags, &itemInfo);

  BOOL isInvisible = itemInfo.flags & kLSItemInfoIsInvisible;
  return isInvisible;
}

Обновление

Aha! / etc, / tmp и / var невидимы, потому что на самом деле они являются символическими ссылками на / private / etc, / private / tmp и / private / var. Если вы скажете Finder напрямую / приватно (используя пункт меню «Перейти к папке»), вы увидите, что они отображаются очень хорошо. (Спасибо @IlDan за подсказку)

Я не уверен, что лучший способ справиться с этим; это имеет значение, только если у вас есть видимая символическая ссылка на файл в скрытой папке. Вероятно, вы могли бы избежать ручного исключения символических ссылок, которые идут в / private, но если сейчас, возможно, вам придется проверять скрытый статус каждой папки на пути вверх по пути.

2 голосов
/ 17 июля 2009

Я думаю, дело в том, что Finder - это интерфейс пользователя дерева файловой системы. Вы хотите спросить Искатель , считает ли он, что файл скрыт или нет, поэтому для этого вам нужен API.

Кажется, что LSCopyItemInfoForURL выполняет работу, как показано в других ответах. Этот пост очень полезен:

Есть несколько способов для вещей быть считается невидимым (в Mac OS X):

  • установлен флаг kLSItemInfoIsInvisible Finder
  • имя файла начинается с периода
  • листинг в файле /.hidden
  • невидимый по происхождению
  • невидимо из-за пакета

Я не копирую все это, это долго, но хорошо написано.

1 голос
/ 17 июля 2009

Философский бит первый:

Файл на самом деле скрыт. Искатель поддерживает свои собственные внутренние данные, чтобы определить, должен ли файл отображаться в списке каталогов или нет; и эта информация может быть передана другим приложениям в системе.

Тем не менее, если вы не внедряете браузер файловой системы, соответствующие определения обычно прозрачно выполняются (без каламбура) внутренней работой NSOpenPanel и друзей.

Если вы осуществляете доступ к файлу программно и сохраняете некоторую видимость владения одним и тем же файлом или не отображаете файл (или нет) в интерфейсе пользователя, на самом деле не имеет значения, считает ли Finder его скрытым или нет.

Что касается технического бита; поскольку любое приложение способно (через вышеупомянутого и почтенного NSOpenPanel) получить доступ к этой информации, оно, вероятно, где-то доступно; но, как уже указывалось, для этого требуется довольно сложное вникание в CoreFoundation и LaunchServices.

Реальная проблема, вероятно, в том, что вам нужно знать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...