2011-02-21

Mac OS X の拡張属性を消す removexattr

Mac OS X の拡張属性 (EA, Extended Attributes) はリソースフォーク、クリエータタイプ、不可視属性、等の HFS+ 固有のレガシーなものから、 com.apple.quarantine のような最近追加されたものまで色々あります。

拡張属性を確認する場合。
ls -l@ file
xattr file


普通は拡張属性を消す必要はないんですが、Windows の FAT32 のボリュームに Mac から拡張属性の付いたファイルをコピーすると、 file と ._file のように2つのファイルとしてコピーされます。できれば ._file のようなファイルは作りたくない。

消す場合は xattr コマンドで -d オプション。 com.apple.quarantine のような名前を指定する必要あり。
xattr -d com.apple.quarantine file

一つのファイルから全ての拡張属性を消すにはシェルスクリプトを書く必要があります。
しかしながら、 xattr (中身は python スクリプト) が妙に遅かったので、 C で書いたものが以下。

removexattr.c
/*
 * Require Mac OS X 10.4 or above.
 * man 2 listxattr
 * man 2 removexattr
 * gcc -O2 -o removexattr removexattr.c
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include <sys/xattr.h>

#define BUFSIZE 0x8000

int main(int argc, const char *argv[])
{
    int i, len;
    uint8_t *namebuf, *p;
    ssize_t size;

    if (argc <= 1) {
        fprintf(stderr,
                "Remove all extended attributes from given files or directories.\n"
                "Usage: %s [file ...]\n", argv[0]);
        exit(1);
    }

    namebuf = (uint8_t *)malloc(BUFSIZE);
    if (namebuf == NULL) {
        fprintf(stderr, "malloc() failed\n");
        exit(1);
    }

    for (i = 1; i < argc; i++) {
        size = listxattr(argv[i], namebuf, BUFSIZE, XATTR_NOFOLLOW);
        if (size <= 0)
            continue;

        p = namebuf;
        len = 0;
        while (len < size) {
            removexattr(argv[i], p, XATTR_NOFOLLOW);
            len = len + strlen(p) + 1;
            p = namebuf + len;
        }
    }

    free(namebuf);

    return 0;
}

コンパイルは (要Xcode)
gcc -O2 -o removexattr removexattr.c
使い方は
./removexattr file

find の -exec で指定ディレクトリ以下全てのファイル、フォルダの拡張属性を消すこともできますが、それはさすがに勇気がいります。

動作確認: Mac OS X 10.6