web-dev-qa-db-ja.com

OS Xのtarballで._fooのようなファイルを取得するのはなぜですか?

OS Xで特定のファイルをタール化​​すると、次のようになります。

tar cvf foo.tar foo

追加のファイルを生成します._foo tarball内:

./._foo
foo

mac以外のオペレーティングシステムで展開した場合にのみ表示されます。だが ._fooがファイルシステムに存在しません!どうしたの?どうすればそれを取り除くことができますか?

73
Jesse Beder

OS Xのtarは、AppleDouble形式を使用して拡張属性とACLを格納します。

$ touch file1 file2 file3
$ xattr -w key value file1
$ chmod +a 'admin allow delete' file2
$ ls -le@ *
-rw-r--r--@ 1 lauri  staff  0 May 25 07:09 file1
    key 5
-rw-r--r--+ 1 lauri  staff  0 May 25 07:09 file2
 0: group:admin allow delete
-rw-r--r--  1 lauri  staff  0 May 25 07:09 file3
$ tar -cf 1.tar *
$ tar -tf 1.tar
./._file1
file1
./._file2
file2
file3

OS Xのtarは、._メンバーをネイティブ形式に戻す方法も知っていますが、他のプラットフォームでアーカイブが抽出されるとき、._ファイルは通常保持されます。 COPYFILE_DISABLEをいくつかの値に設定することで、メタデータを含めないようにtarに指示できます。

$ COPYFILE_DISABLE=1 tar -cf 2.tar file*    
$ tar -tf 2.tar
file1
file2
file3
  • Copyfile関数はman copyfileで説明されています
  • ls -l@は拡張属性のキーとサイズを示し、ls -leはACLを出力します
  • xattr -lは、拡張属性のキーと値をリストします
  • xattr -cは、すべての拡張属性をクリアします(-dは単独では使用できません)
  • chmod -NはACLを削除します
  • OS Xで作成されたZipファイルは、__ MACOSXフォルダーを使用して同様のメタデータを格納します

拡張属性として保存される情報:

  • リソースフォーク(リソースフォークは10.4以降拡張属性になっています)
    • Finderで設定されたカスタムアイコンとIcon\rファイルの画像
    • PSDファイルのメタデータ
    • Scptファイルに保存されているオブジェクト、AppleScriptエディタウィンドウの状態、スクリプトの説明
  • エイリアスに関する情報(拡張属性が削除されると、エイリアスは機能しなくなります)
  • インターネットからダウンロードされたファイルの隔離ステータスまたはソースURL
  • Spotlightコメント
  • TextEditで保存されたファイルのエンコーディング
  • TextMateで開いたファイルのキャレット位置
  • スキムノート
81
Jesse Beder

bsdtar 3.0.3 - libarchive 3.0.3(およびおそらく以前)では、--disable-copyfileと呼ばれるbsdtarコマンドに、._ファイルの作成を抑制する新しいオプションがあります。

# on Mac OS X
# /usr/bin/tar -> bsdtar
ls -l /usr/bin/tar    

# from man bsdtar
--disable-copyfile
        Mac OS X specific.  Disable the use of copyfile(3).
13
mdm

._ファイルは、他の回答で述べたようにリソースフォークです。ただし、tarを使用するときにこれらを取り除くためのより良い方法があります。

export COPYFILE_DISABLE=true
tar cvf foo.tar foo

これらのファイルをクリーンアップするためのdot_cleanユーティリティもあります(通常、外部ストレージに使用されると思います)。

1
jtbandes

以下は、これらのファイルを削除するためのpythonスクリプトです。一般的なOSで動作するはずです。

Not十分にテストされており、自己責任で使用してください!

import os
import os.path

def dot_clean(folder):
    files = os.listdir(folder)
    for file in files:
        full_name = folder + "/" + file
        if os.path.isdir(full_name):
            dot_clean(full_name)
        Elif file.startswith("._"):
            os.remove(full_name)

dot_clean('.')            
0
Aivar