続・Mac で p7zip を使って .DS_Store を除外したアーカイブを作成する

前のネタの続き。「~/.bashrc に関数を登録しておくと面白いかも」とか書いたので ~/.bashrc を改造してみました。

前のネタ → Mac で p7zip を使って .DS_Store を除外したアーカイブを作成する

今まで CotEditor や Git なんかのショートカットも alias で色々書いてましたが、関数で書いた方が書きやすいですね。

7z はアーカイブ形式毎に実行コマンドを分けて、圧縮処理用の関数を呼び出すようにして引数で圧縮レベルの設定が出来るようにしてみました。圧縮レベルの指定が無い場合は標準レベルで圧縮。.DS_Store を含めないのは前のネタからの引用。

p7z_zip (){ local type="zip";   p7z_compress "$@"; }
p7z_7z  (){ local type="7z";    p7z_compress "$@"; }
p7z_compress(){
    # 引数1が数字
    if [ "$(echo "$1" | egrep "^[0-9]$")" ]; then
        # 引数1が数字 & 引数の総数が1より大きい
        if [ "$#" -gt "1" ]; then
            local l="$1"
            shift
        # 引数1が数字 & 引数の総数が1より小さい & 引数のファイルまたはディレクトリが存在する場合
        elif [ -e "$1" ]; then
            echo "圧縮レベルの値と同じ名前のディレクトリまたはファイルが存在します"
            echo "圧縮レベルを設定するか./をつけて実行して下さい"
            return
            # 引数1が数字 & 引数の総数が1より小さい & 引数のファイルまたはディレクトリが存在しない場合
            else
                echo "ファイルが見つかりません"
                return
        fi
    # 引数1が数字以外
    else
        local l="5"
    fi
    local name="$(echo "$1" | sed -e "s|^\./|${PWD}/|")"
    [ -e "${name}.${type}" ] && name+="$(date +%Y%m%d_%H%M%S)"
    local archive="${name}.${type}"
    cat <<-_EOT_
        ファイル名: ${archive}
        圧縮タイプ: ${type}
        圧縮レベル: ${l}
    _EOT_
    7z a -mx=${l} "${archive}" "$@" -xr\!.DS_Store && 7z l "${archive}"
}

※ローカル変数使ってなかったりとか関数名が数字だったりとか致命的な問題があったので修正(2012年10月10日)

最初の頃は `PATH` しか書いてなくて変数しか書けないものだと思ってましたw

今回面倒だったのは「圧縮レベル用の引数(0-9)がファイル名やフォルダ名と被ったらどうするか」ってところ。Automator で作成するアプリケーションならファイルのパスはフルパスになるので困らないんですが、ターミナルでカレントディレクトリのファイルを圧縮したいときなどにちょっと困ります。

  1. 引数1 が数字以外の場合
  2. 引数1 が数字で 引数2 が数字以外の場合
  3. 引数1 と 引数2 が数字で、カレントディレクトリに 引数1 と同じファイルが存在する場合
  4. 引数1 が数字で 引数2 が無く、カレントディレクトリに 引数1 と同じ名前のファイルが存在する場合
  5. 引数1 が数字で 引数2 が無く、カレントディレクトリに 引数1 と同じ名前のファイルが存在しない場合

コマンドは

bash
$ p7z_zip 圧縮レベル ファイル

となるわけですが、「0」という名前のファイルがあると

bash
$ p7z_zip 0 0 #圧縮レベル0で「0」を圧縮

になる可能性もあったり

bash
$ p7z_zip 0 #圧縮レベル自動で「0」を圧縮

になる可能性もあるわけで。

とりあえず引数が2以上なら最初の数字は圧縮レベルの数字ってことにしたりして、どうしようもないのは return で止めることにしました。自分だけが使うなら必ず圧縮レベルを指定するような方法でいいんですけど勉強も兼ねて寄り道。

同一名のアーカイブがあったときの対処をどうしようかと思ったけど while の使い方わからんからアーカイブに日付を付けることにした。あとは ./ で始まるパスだと上手くいかなかったりしたのでフルパスに置き換えとか(iTerm の調子が悪かっただけかも)。

圧縮後に `7z l' を実行するようにしておくと圧縮率の確認かも出来て面白い。

bash
$ p7z_zip 0 ./bin

ファイル名: /Users/mattintosh/local/bin.zip
圧縮タイプ: zip
圧縮レベル: 9

7-Zip [64] 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
p7zip Version 9.20 (locale=utf8,Utf16=on,HugeFiles=on,2 CPUs)
Scanning

Creating archive /Users/mattintosh/local/bin.zip

Compressing  bin/ss
Compressing  bin/winecase
Compressing  bin/winevnc

Everything is Ok

7-Zip [64] 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
p7zip Version 9.20 (locale=utf8,Utf16=on,HugeFiles=on,2 CPUs)

Listing archive: /Users/mattintosh/local/bin.zip

--
Path = /Users/mattintosh/local/bin.zip
Type = zip
Physical Size = 1832

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2012-10-06 22:09:20 D....            0            0  bin
2012-09-30 22:35:32 .....          460          236  bin/ss
2012-10-02 16:41:18 .....         1918          834  bin/winecase
2012-10-02 17:04:44 .....          584          370  bin/winevnc
------------------- ----- ------------ ------------  ------------------------
                                  2962         1440  3 files, 1 folders

そもそも 7z ってコマンドそこまで長くないし、Finder 用に Automator でシェルスクリプトを作成するとしてもここまで長々と書かなくてもいいはず…。

遊びでなんとなく始めてみたけど .bashrc 弄るのは楽しい(・∀・)