エイリアスのサイズがバカでかくて驚きました

エイリアスのサイズってこんなものなんでしょうか。小さくする方法とかあるのでしょうか?


JPEG画像ファイルのサイズに関わらず、そのエイリアスを作ると、エイリアスのサイズは2.6MBになります。100KBのJPEGであっても2.6MBという**みたいなサイズです。以前はこんなサイズではなかった筈なのにどうしたんでしょう。


これがフォルダの場合だと、標準のフォルダのエイリアスのサイズは5.6MBもあります。

ところが、Ableton Liveというアプリで作られるプロジェクトフォルダ(編集データや音源が入ったフォルダで、カスタムアイコンが付いています)のエイリアスの場合は76KBです。以前は全てのエイリアスがこの程度のサイズだったように気がします。


これって、おそらくOSの仕様かと思うのですが、これだとホイホイとエイリアスを作るのは気が引けるというものです。原因とサイズを小さくする対策ってあるものなんでしょうか? お知恵をお貸しください。


環境です。

MacBook Air 13-inch, Mid 2013

プロセッサ 1.3 GHz Intel Core i5

メモリ 8 GB 1600 MHz DDR3

グラフィックス Intel HD Graphics 5000 1024 MB

ソフトウェア OS X 10.8.5(12F45)

MacBook, Mac OS X (10.5.8)

投稿日 2014/09/22 20:36

返信
返信: 12

2014/09/22 22:27 combo への返信

ファイルサイズのほとんどがカスタムアイコンの画像データです。


シンボリックリンクにするとサイズが小さくなります。ただし、(Lion 以降のことは分かりませんが、少なくとも Snow Leopard までだと) Automator や AppleScript で問題となる場合があるので注意が必要です。


個人的には、サイズを気にしないのが一番かなと思ってます。


ご参考

エイリアスがでかい!

https://discussionsjapan.apple.com/thread/10129217


ーーーーー


追記: フォルダのエイリアスの場合、Snow Leopard ではリソースフォークだけでなく、データフォークにもリンク情報と画像データが格納されるので、さらにサイズが大きくなってます。Lion 以降も多分同じだと思います。

2014/09/23 01:28 Hiro__S への返信

誤: フォルダのエイリアスの場合、Snow Leopard ではリソースフォークだけでなく

正: フォルダのエイリアスの場合、Snow Leopard ではリソースフォークだけでなく


フォルダもファイルもリソースフォークとデータフォークの両方にデータが格納されますね...。失礼しました。フォルダのエイリアスが大きくなる原因は...何となくは分かったんですが、ちゃんと調べてないのでやめときます...。


ーーーーー


あと、シンボリックリンクではなく、あくまでもエイリアスで...というなら、オリジナルファイルに小さなカスタムアイコンを貼付けてからエイリアスを作ると小さくなるんじゃないでしょうか。


私はあまり面倒なことをしたくないので、サイズのことは気にせずにエイリアスを使ってます。

2014/09/24 05:51 Hiro__S への返信

Hiro.S さん、どうもありがとうございました。


カスタムアイコンを貼付けてないオリジナルのサイズが小さいのは、システムに格納されてるであろう標準的なアイコンを参照するような仕様なのかな。それは上手いやり方だと思います。ならばエイリアスの場合はそのオリジナルのアイコンデータを参照する仕様にしておけば、いたずらに容量が増えなくていいなと思ったんですが、今これを書いているときに、オリジナルが外付けのHDDにある場合は、そのHDDをアンマウントするとエイリアスは白紙アイコンになってしまって、それも良くないなあなどと思った次第です。
ぶっちゃけ、エイリアスの方は32×32サイズ以下のアイコンだけ貼付けてくれれば充分なんですけどね。環境設定でエイリアスにはビッグアイコンは貼付けないのを選択できるようにしてくれれば嬉しいのですが・・・。Hiro.S さんのおっしゃるように、ストレージの方もテラバイトオーダーになった今、気にしない方が良いのかもしれませんね。 ただ、MacBook Airの場合は、やはりもったいないんですよねえ。今回は勉強になりました。

2014/09/25 06:41 combo への返信

こんばんは


もう解決済みかも知れませんが、エイリアスファイルを小さくする方法はある、ということで、参考までに私が個人的に使っているスクリプトを載せておきます。要は、alis リソース以外のリソースを削除したエイリアスファイルを作るというだけです。OSX 10.6.8 と 10.5.8 で動作を確認していますが、それ以降のシステムではテストしていません。/usr/bin/rez と /usr/bin/derez を使うので、Developer Tools (Xcode) をインストールしている必要があると思います。最近のシステムでは、Rez と DeRez のパスも違うかもしれません。必要に応じて修正してください。


OSX 10.6 以降では、Automator の Run Shell Script アクションでこのスクリプトを呼ぶサービスを作っておけば、ファイルかフォルダを選択してコンテクストメニューからサービスを呼ぶことで、選択範囲にあるエイリアスファイルをスリム化できます。フォルダを選択した場合は、そのフォルダ配下のディレクトリ木にあるすべてのエイリアスファイルを対象にします。但しパッケージの内部は触りません。


現状では、alis データをリソースフォークとデータフォークの両方に持つエイリアスファイルを作るようになっていますが、スクリプト中の CLEAR_DATA_FORK を true にすれば、データフォークが空の最小サイズのエイリアスファイルを作ります。なお、権限がないとか、ロックされているとかで変更できないエイリアスファイルは黙って無視します。


Automator のサービスはこんな風になります。 Run Shell Script アクションでは、Shell = /bin/bash, Pass input = as arguments とします。


ユーザがアップロードしたファイル




スクリプトは以下の通りです。



#!/bin/bash /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby -w <<'EOF' - "$@" # # slim alias v0.32 # written by Hiroto, 2014-09 # # # ARGV = <file or directory> [<file or directory> ...] # require 'osx/cocoa' include OSX CLEAR_DATA_FORK = false # true to put 'alis' in resource fork only and clear data fork; false to put 'alis' in both forks while File.exist?(TEMPFILE = "/tmp/slim_alias.#{rand(1e6)}.r") do end Signal.trap("EXIT") { File.delete TEMPFILE if File.exist? TEMPFILE } def quoted_form(s) # # string s : source string # return string : s's quoted form for use in shell # * e.g., given s = a'b, quoted form of s = 'a'\''b' # %q['%s'] % s.gsub(/'/) {%q['\'']} end def slim_alias1(f) # # string f : POSIX path of alias file # * put 'alis' in both resource fork and data fork # f = quoted_form(f) %x[ exec 2>/dev/null /usr/bin/derez -only 'alis' #{f} > "#{TEMPFILE}" || # derez 'alis' in resource fork /usr/bin/derez -useDF -only 'alis' #{f} > "#{TEMPFILE}" || # or derez 'alis' in data fork exit # or exit /usr/bin/rez -o #{f} -noResolve output "#{TEMPFILE}" # put 'alis' in resource fork (overwrite resource fork) /usr/bin/rez -useDF -o #{f} -noResolve output "#{TEMPFILE}" # put 'alis' in data fork (overwrite data fork) ] end def slim_alias2(f) # # string f : POSIX path of alias file # * put 'alis' in resource fork and clear data fork # f = quoted_form(f) %x[ exec 2>/dev/null /usr/bin/derez -only 'alis' #{f} > "#{TEMPFILE}" || # derez 'alis' in resource fork /usr/bin/derez -useDF -only 'alis' #{f} > "#{TEMPFILE}" || # or derez 'alis' in data fork exit # or exit /usr/bin/rez -o #{f} -noResolve output "#{TEMPFILE}" && # put 'alis' in resource fork (overwrite resource fork) : > #{f} # and clear data fork ] end def scan_aliases(p) # # string p : absolute POSIX path of directory or file # return array : aliases in directory tree rooted at p if p is directory; [p] if p is alias file; otherwise [] # aa = [] ws = NSWorkspace.sharedWorkspace uti = ws.typeOfFile_error(p, nil) if uti == 'public.folder' de = NSFileManager.defaultManager.enumeratorAtPath(p) while (n = de.nextObject) != nil do f = p + '/' + n.to_s de.skipDescendants if ws.isFilePackageAtPath(f) # ignore package contents if de.fileAttributes.objectForKey(NSFileType) == NSFileTypeRegular aa << f if ws.typeOfFile_error(f, nil) == 'com.apple.alias-file' end end elsif uti == 'com.apple.alias-file' aa << p end aa end def main(argv) # # array argv : array of every target file or directory where targe tree is rooted at # argv.map {|a| File.expand_path(a)}.each do |f| scan_aliases(f).each do |a| if CLEAR_DATA_FORK begin # skip if data fork == 0 and resource fork <= 4096 next if File.size(a) == 0 && File.size(a + '/..namedfork/rsrc') <= 4096 rescue end slim_alias2(a) else begin # skip if alias size <= 8192 next if File.size(a) + File.size(a + '/..namedfork/rsrc') <= 8192 rescue end slim_alias1(a) end end end end main(ARGV) EOF



私が使っている範囲では、特に問題はないですが、一切保証はできません。実際に使用される場合は、どうか、ご自身で十分にテストしてから、ご自身のリスクでお使いください。

コードの使用と変更は自由に行なっていただいて結構です。


ではでは。

2014/09/27 14:51 chandana への返信

chandanaさま

どうもありがとうございました。こんな方法もあるのかとちょっとビックリしてます。

Automatorはいつも使ってるんですが、シェルスクリプトとなると自分にその知識が無くてなかなかハードルが高いです。

お教えして頂いたものを丸コピーすれば実現できるでしょうが、実行に移すのはもう少し勉強してからにしたいと思います。

今後ともよろしくお願いいたします。

2014/09/27 20:41 chandana への返信

エイリアスのデータフォークにはリンク情報とカスタムアイコンの画像データが格納されてますが、リソースフォークとは形式が異なり DeRez や Rez では処理できないようです。-useDF で扱えるのは dfont のようにリソースフォークをそのままデータフォークにコピーしたものだと思います。


なので、-useDF オプション付きの DeRez と Rez は不要ではないでしょうか?また、リソースフォークの内容 (alis) をそのままデータフォークに書き込むのではなく、それなりに作り替える必要があると思いますが、いかがでしょうか?(とは言っても、どうやったら良いものか分かりませんが...)


現状で問題とならないのはデータフォークの情報を使用してないからで、将来的には問題となりそうな気がしないでもないです。いっそのこと CLEAR_DATA_FORK = true として、Leopard 以前のカタチにした方が良いのかなとも思ったりしてます。


あと、細かいことですみませんが、カスタムアイコンを削ったら、フラグを落とした方が良いような。こんな感じでしょうか。

/usr/bin/SetFile -a c #{f}


# ほかのスレッドで ruby のコードを見た時に、もしやと思ったのですが、やはりそうでしたか。US のボードを時々見ては勉強させてもらってます。ありがとうございます。

2014/09/28 13:32 Hiro__S への返信

ご指摘ありがとうございます。おっしゃる通りですね。エイリアスファイルのデータフォークに書かれているのは、alis データではなくて、bookmark データでした。データフォークに alis を書くと、bookmark を期待しているプログラムで問題が起こる可能性が高いです。


ところで、NSURL のメソッドや CFURL の関数を使えば、最小限の bookmark を作れますが、残念ながら、この最小限の bookmark は、エイリアスファイルに書き出せません。一方で、エイリアスファイルに書き出せるように bookmark を作ると、アイコンデータが含まれてしまいます。どうやら、なんとしてもアイコンデータを埋め込ませたいらしい。


というわけで、肥大化したエイリアスファイルのデータフォークの処遇としては、そのまま放っておくか、削除するかのどちらかしかなく、アイコンをなくして小さくするというオプションはないようなので、スクリプトをそのように修正しました。現状ではデータフォークを削除するようにしてあります。なお、データフォークをそのまま残す選択をすると、エイリアスファイルのサイズは半分程度にしかできません。


それと、データフォークを削除する場合は、カスタムアイコンビットもクリアするようにしておきました。カスタムアイコンなんて久しく使わないので、すっかり忘れていた。(正確には、データフォークを削除しない場合でも、データフォークに bookmark データがないときは、カスタムアイコンビットをクリアすべきですが、bookmark の有無のチェックが面倒なので、 あると仮定してカスタムアイコンビットはそのままにしてあります。)



# US のボードでは、最近は主に rubycocoa で遊ばせてもらっています。何かのお役に立っているとすれば光栄です。でも、それももうすぐ終わりかもしれません。どうやら OSX 10.10 では、ruby 1.8 が丸ごとなくなっているらしく、つまり rubycocoa も標準では動かなくなるようです。朗報は、rubycocoa 1.2.0 がついに、ruby 2.0 以降に対応したことです。これで、志ある者は、最新版の rubycocoa をインストールしさえすれば、これまでどおり rubycocoa の恩恵に与れるはずなのですが、いかんせん、サポートサイトで質問に答えるのに、いちいちあれこれインストールしてくれと云うのも面倒かなと思う今日この頃です。



以下、修正版です。


#!/bin/bash /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby -w <<'EOF' - "$@" # # slim alias v0.33 # written by Hiroto, 2014-09 # # # ARGV = <file or directory> [<file or directory> ...] # require 'osx/cocoa' include OSX CLEAR_DATA_FORK = true # true to clear data fork which may contain bookmark data, false otherwise. while File.exist?(TEMPFILE = "/tmp/slim_alias.#{rand(1e6)}.r") do end Signal.trap("EXIT") { File.delete TEMPFILE if File.exist? TEMPFILE } def quoted_form(s) # # string s : source string # return string : s's quoted form for use in shell # * e.g., given s = a'b, quoted form of s = 'a'\''b' # %q['%s'] % s.gsub(/'/) {%q['\'']} end def slim_alias1(f) # # string f : POSIX path of alias file # * put 'alis' in resource fork, preserving data fork which may contain bookmark data # f = quoted_form(f) %x[ exec 2>/dev/null /usr/bin/derez -only 'alis' #{f} > "#{TEMPFILE}" || # derez 'alis' in resource fork exit # or exit /usr/bin/rez -o #{f} -noResolve output "#{TEMPFILE}" # put 'alis' in resource fork (overwrite resource fork) ] end def slim_alias2(f) # # string f : POSIX path of alias file # * put 'alis' in resource fork, clear data fork and clear custom icon bit # f = quoted_form(f) %x[ exec 2>/dev/null /usr/bin/derez -only 'alis' #{f} > "#{TEMPFILE}" || # derez 'alis' in resource fork exit # or exit /usr/bin/rez -o #{f} -noResolve output "#{TEMPFILE}" && # put 'alis' in resource fork (overwrite resource fork) : > #{f} && # and clear data fork /usr/bin/SetFile -a c #{f} # and clear custom icon bit ] end def scan_aliases(p) # # string p : absolute POSIX path of directory or file # return array : aliases in directory tree rooted at p if p is directory; [p] if p is alias file; otherwise [] # aa = [] ws = NSWorkspace.sharedWorkspace uti = ws.typeOfFile_error(p, nil) if uti == 'public.folder' de = NSFileManager.defaultManager.enumeratorAtPath(p) while (n = de.nextObject) != nil do f = p + '/' + n.to_s de.skipDescendants if ws.isFilePackageAtPath(f) # ignore package contents if de.fileAttributes.objectForKey(NSFileType) == NSFileTypeRegular aa << f if ws.typeOfFile_error(f, nil) == 'com.apple.alias-file' end end elsif uti == 'com.apple.alias-file' aa << p end aa end def main(argv) # # array argv : array of every target file or directory where target tree is rooted at # argv.map {|a| File.expand_path(a)}.each do |f| scan_aliases(f).each do |a| if CLEAR_DATA_FORK begin # skip if data fork == 0 and resource fork <= 4096 next if File.size(a) == 0 && File.size(a + '/..namedfork/rsrc') <= 4096 rescue end slim_alias2(a) else begin # skip if resource fork <= 4096 next if File.size(a + '/..namedfork/rsrc') <= 4096 rescue end slim_alias1(a) end end end end main(ARGV) EOF

2014/09/28 21:10 chandana への返信

修正版ありがとうございます。なんか催促してしまったようで、申し訳ないやら、ありがたいやら。


# RubyCocoa の件は覚悟してました。私も残念です。PyObjC も同じ運命なのでしょうかね。次期 OS では AppleScript - JavaScript で同等のことができるようになる?とのことですが、処理速度には期待しない方が良いのかな?まあ、その辺は出てのお楽しみということでしょうね。

2014/10/03 20:34 chandana への返信

chandanaさん、返事が遅れて申し訳有りません。詳しい対処方法をありがとうございました。
現状は解決はしてないのですが、さりとて教えて頂いた内容は僕には高度すぎて・・・

これはこういうものということで今は納得してます。
とりあえず、せめて教えて頂いたことの半分でも理解できるようになるまでは、手を出すと火傷しそうなので今回は見送るつもりです。
せっかく教えて頂いたのに、僕の方の知識不足で申し訳有りません。今後ともよろしくお願いします。

2014/11/17 17:18 combo への返信

横からすみません。

chandanaさんのシェルスクリプト凄いですね!私もエイリアスの軽量化の方法を探していてここに行き当たりまして、

(シンボリックリンクは確かに非常に小さくなって良いのですが、ファイルとして認識されないのか検索で引っかからなくなってしまったのでやめました)


で、ご紹介のシェルスクリプトを試させて頂いたのですが、ほんとスッキリです!

およそ5分の1くらいのサイズでしょうか。


私はスクリプトとかコマンドラインとかはホントど素人なのですが、そんなに難しくなく出来たので、
comboさんもぜひ実行されると良いと思いました!


やり方は簡単です。


1. Automatorを立ち上げたら表示される新規作成画面では 歯車マークの『サービス』を選択

2. 表示されたウィンドウの右上はでは サービスが受け取る選択項目は『ファイルまたはフォルダ』検索対象は『すべてのアプリケーション』を選択

3. 左上のアクションのライブラリのリストから『シェルスクリプトを作成』を選択

4. 左側に『シェルスクリプトを実行』のウィンドウが現れるので、そしたらシェルは『/bin/bash』に、入力の引き渡し方法は『引数として』を選択し、

5. その下の窓に何か表示されますが、無視してその上からchandanaさんの紹介して下さった『スクリプト( #!/bin/bashで始まって main(ARGV) EOFで終わる)』を上書きペースト。

6. そしたらファイルメニューで保存を選択して「エイリアス軽量化」とか適当な名前を付けて保存。

7. あとは、Finderでスリム化したいエイリアスを選択してサービスメニューから使うだけです!


以上

いかがでしょう?ほんと簡単でしたよ!


ちなみに保存されたサービスファイルは、

ユーザ/home/Library/Services/ にありました (私はこれも初めて知りましたw)



勉強になりました、ありがとうございました。

このスレッドはシステム、またはAppleコミュニティチームによってロックされました。 問題解決の参考になる情報であれば、どの投稿にでも投票いただけます。またコミュニティで他の回答を検索することもできます。

エイリアスのサイズがバカでかくて驚きました

Apple サポートコミュニティへようこそ
Apple ユーザ同士でお使いの製品について助け合うフォーラムです。Apple Account を使ってご参加ください。