So-net無料ブログ作成

MacOSの隠しファイルを削除する [Ruby]

今回はちょっと違う話題を・・。

私は、Macを利用しているんですが、MacOSでは「リソースフォーク」とか言って、ファイルの属性が書かれているファイルが隠しファイルとしてファイル毎に作成されたりします。Mac上でFinderなど普通のアプリを使っている時には特に問題はないのですが、NASを利用してファイル共有していると、結構邪魔なため、これらの隠しファイルを削除するツールを作ってみました。

見えている隠しファイルは「.DS_Store」と各ファイル毎に作成されている「._<filename>」、隠しディレクトリの「.AppleDouble」。ついでに古いディレクトリだと「2EDS_~!3」と言うのも見えています。さらに、ツールを作っている時に気が付いた「._.DS_Store」。かなり前からMacでNASを使ってファイル共有をしてるんですが、その間にNASの入れ替えでターミナルなんかを使って、ファイルの移動などをさせているうちにいろんな種類の隠しファイルが出来ている様です。特に「._.DS_Store」なんかは、隠しファイルの隠しファイルになってるみたいです・・・。

ツールの仕様は下記の通り。

  • 「.」で始まるファイルを削除
  • 「.」で始まるディレクトリはその中身全てと共に削除
  • ファイル「2EDS_~!3」を削除
  • 引数で指定されたディレクトリ以下、全てのサブディレクトリが対象


と言う感じで、処理対象はデータを保存しているディレクトリのみのため、仕様はかなり簡素化してます。データと共に設定などを隠しファイルで持っているディレクトリには使用できません。

で、サブディレクトリの探索ですが、再帰で処理して行くと深い階層のディレクトリが処理できなくなる可能性があるため、ディレクトリを見つけたらキュー(今回は配列)に詰めて行き、現在のディレクトリの中の隠しファイルを削除し終わったら、次のディレクトリに進むと言う感じにしました。

後、「._.DS_Store」と言う隠しファイルは「.DS_Store」を削除した瞬間に同時に削除される。つまり「.DS_Store」に対するリソースフォークになってしまっている様子です。このファイルの存在と振る舞いに気づく前は「ファイルが無い」と例外が発生して処理が止まってしまっていたのでした。

また、文字列の処理をするのが面倒だったので、削除の作業は実際にそのディレクトリに移動(chdir)して、作業する様にしています。まあ、これはどっちがいいのかよくわからないですね。

と言う感じで作ったRubyスクリプトをアップしようかと思いましたが、このブログは画像、動画、音声しかアップできない様です。まあ、そんなに長いソースでもないので、ここにコピーしときます。

ちなみに、実行したRubyのバージョンは「ruby 1.8.7 (2012-02-08 patchlevel 358) [universal-darwin10.0]」です。

# 指定されたディレクトリ以下にある.ファイルを削除
# サブディレクトリも検索する
# .ディレクトリは中のファイルも全て削除
# 「2EDS_~!3」も削除
# 
# 使用法:ruby del_dot.rb <dir_name>

# ディレクトリを検索して、.ファイル、.ディレクトリを削除する
class DelDot
    @dir_stack        # 処理すべきディレクトリ名(フルパス)を格納する配列
    
    # 初期化
    def initialize(root)
        @dir_stack = Array[root]
    end
    
    # .ファイルの削除
    def del_dot(file)
        if (file =~ /^\..+/) then
            File.delete(file)
            print 'delete ', file, "\n"
        elsif (file == "2EDS_~!3") then
            File.delete(file)
            print 'delete ', file, "\n"
        end
    end
    
    # .ディレクトリの削除:ディレクトリ内のファイルは全て削除する
    def del_dotdir(dir)
        procdir = Array.new.push(dir)
        deldir = Array.new.push(dir)
        
        while procdir.size != 0
            curdir = procdir.shift
            Dir.chdir(curdir)
            print '---------------------- ', curdir, "\n"
            Dir.foreach(Dir.pwd) { |file|
                if File.ftype(file) == "directory" then
                    if (!(file == '.') && !(file == '..')) then
                        procdir.push(Dir.pwd + '/' + file)
                        deldir.push(Dir.pwd + '/' + file)
                    end
                else
                    File.delete(file)
                    print 'delete ', file, "\n"
                end
            }
        end
        
        Dir.chdir(dir + '/..')
        deldir.reverse_each { |item|
            Dir.delete(item)
            print 'delete ', item, "\n"
        }
    end
    
    # 単一ディレクトリの処理
    def proc_dir(cur)
        Dir.chdir(cur)
        Dir.foreach(Dir.pwd) { |file|
            if File.exist?(file) == true then
                if File.ftype(file) == "directory" then
                    if (file =~ /^\..+/) then        # .ディレクトリの処理
                        if (!(file == '.') && !(file == '..')) then
                            del_dotdir(Dir.pwd + '/' + file)
                        end
                    else                            # ディレクトリの登録
                        if (!(file == '.') && !(file == '..')) then
                            @dir_stack.push(Dir.pwd + '/' + file)
                        end
                    end
                else
                    del_dot(file)
                end
            end
        }
    end
    
    # メイン処理
    def proc
        while @dir_stack[0] != nil
            cur = @dir_stack.shift
            print '---------------------- ', cur, "\n"
            proc_dir(cur)
        end
    end
end

# 引数をクラスに渡す
dir_name = ARGV[0]
if dir_name != nil then
    script = DelDot.new(dir_name)
    script.proc
end


処理、ソースの善し悪しはさておき、初めて開発系のブログの様な雰囲気になりましたかね??

*

と言うことなんですが、記事を書き終えた後、バグを2個程見つけまして、上記はそれを修正したものとなってます。・・が、既にある程度の処理が終わっている(バグで完全に処理が終わってなかった)ディレクトリに対して実行しただけなので、もしかしたら、修正がうまく行ってない可能性もあったりするかも・・・。

自分用のツールならほっておく(で、運用で対応する)様な内容でしたが、公開するとなると何となく気持ち悪くて、よけいな対応をしてしまいますね・・。更なるバグの指摘やRuby的にはこうした方がいいんじゃないのと言う様なご意見がございましたら、コメントをお願いします。後、根本的なアルゴリズムも・・。



ナウでヤングなレンタルサーバー!ロリポップ!

nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

ブログを作る(無料) powered by So-netブログ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。

×

この広告は1年以上新しい記事の更新がないブログに表示されております。