要点
- Windowsで解凍しても文字化けしない
-
.DS_Store
等の不要な隠しファイルを含まない1
上記2点を満たしたZIPファイルをコマンドラインシェル(zsh)から作成します.
きっかけ
macOSでZIPファイルを作成する際にはFinderの「圧縮」機能を利用できます.
しかしこの方法で作成したZIPファイルは,Windows PCへ送付した場合に困ることが二つあります.
その1.ファイル名が文字化けする
macOSで作成したZIPファイルをWindowsで解凍すると,ファイル名に含まれる日本語が文字化けしてしまいます.
これはmacOSとWindowsで用いられる文字コードが異なるために起きます2.
Windows上で作ったZIPファイルはmacOSで開いても大丈夫なのに逆はダメなので,仕方ないですが Windowsで解凍しても文字化けしないZIPファイルを作成したいところです.
その2.不要なファイルが入る
macOSでは.DS_Store
のようなOS固有のファイルが自動で生成されます.
macOS上では隠しファイルになっているため,不要であるにも関わらずZIPファイルへの圧縮時に含めてしまうことがあります.
そのままWindowsユーザに送付するとお小言をいただくので,仕方ないですが このような他OSでは不要なファイルを除いた状態でZIPファイルを作成したいです.
利用するソフト
今回は
の2つのソフトを利用します.
どちらもHomebrewを利用してインストールできます.
brew install fd
brew install p7zip
指定したフォルダをZIPファイルに圧縮する
現在の作業ディレクトリ直下にあるディレクトリ./target
をtarget.zip
という名前で圧縮しましょう.
次のコマンドを実行すれば,きっとうまく行くはずです.
fd --type file . target -X 7z a -tzip -scsWIN target.zip {}
以下ではこのコマンドがどのように動いているのか解説します.
Windowsで文字化けしないZIPファイルを作る
p7zip3を用いてWindowsで文字化けしないzipファイルを作成するコマンドは
7z a -tzip -scsWIN 出力ファイル名 圧縮するファイル・ディレクトリ
です.
重要なのが-scsWIN
オプションです.
-scs
は Set charset for list files のことで,-scsWIN
とすることでWindowsの文字コードに合わせてくれます.
また7z a
コマンドは通常7-Zip形式の圧縮ファイルを作成しますが,-tzip
オプションを利用することで出力ファイルの形式をZIPファイルに変更できます.
2023年夏頃から,Windowsに標準搭載されているエクスプローラで7-Zipファイルの解凍可能になりました4.
なので7-Zip形式のままでも一応大丈夫ですが,今回はWindowsで一般的に利用されるZIP形式で作成します.
隠しファイルを取り除く
fd
コマンドを利用して隠しファイルを取り除きます.
fd --type file . 対象のディレクトリ
で指定したディレクトリ以下に存在するファイルを検索します.
この際,デフォルトでは隠しファイルは検索結果に含まないので5,.DS_Store
等の不要なファイルを弾くことができます.
デフォルトではファイルとディレクトリの両方を表示するので,--type file
オプションでファイルのみを検索するよう指定します.
これに加えて-X
オプション6を追加することで検索結果にコマンドを実行できます.
fd
による検索結果を利用するには,実行したいコマンドのファイル名を指定する箇所に{}
を記述します.
具体的に
fd --type file . 圧縮したいディレクトリ名 -X 7z a 出力ファイル名.zip {}
とすることで,fd
が圧縮したいディレクトリ以下に含まれるファイルを検索し,その結果が{}
で記述した7z a
コマンドの圧縮対象のファイル指定部分に適用されます.
以上のことを組み合わせることで,隠しファイルを取り除きながらWindowsでも文字化けしないZIPファイルを作成できます.
zshの関数にまとめる
先ほどのコマンドを毎回入力するのは面倒!という人は,zshの関数にまとめて.zshrc
に記述しておきましょう.
ディレクトリ名を指定し,当該ディレクトリ以下のファイルをZIPファイルに圧縮する関数は以下の通りです.
function zipwin ()
{
if [ -z $1 ] || [ $1 = . ]; then
# 現在の作業ディレクトリをZIPファイルに圧縮する.
local zip_name="$(basename $(pwd)).zip"
fd --type file --strip-cwd-prefix . -X 7z a -tzip -scsWIN $zip_name {}
else
# 指定したディレクトリをZIPファイルに圧縮する.
local loc_dir=$(dirname $1)
local target=$(basename $1)
local zip_name="$(pwd)/${target}.zip"
fd --type file --base-directory=$loc_dir . $target -X 7z a -tzip -scsWIN $zip_name {}
fi
# 作成したZIPファイルに含まれるファイルを確認する.不要であればコメントアウトしてください.
7z l $zip_name
return 0
}
上記の関数を用意すれば
zipwin 圧縮したいディレクトリ
で指定したディレクトリをWindowsでも文字化けしないZIPファイルに圧縮できます.
引数がない場合,あるいは.
(作業ディレクトリ)を指定した場合は,作業ディレクトリ以下のファイルをZIPファイルに圧縮するようにしています(if
文のtrue
の方ですね).
ここでfd
に--strip-cwd-prefix
オプションを追加しています.
作業ディレクトリを対象にfd
で検索をかけると,検索結果のファイルパス最初に./
が付きます.
そのまま7z a
コマンドに流し込むと,ディレクトリ構造が壊れて全てのファイルが同じディレクトリに保存されてしまいます.
そこで検索結果から./
を取り除くオプションである--strip-cwd-prefix
を追加しました.
また,ディレクトリを指定した場合(else
以降の方)は--base-directory=
オプションを追加しています.
例えばfd . hoge/fuga
のようにサブディレクトリであるfuga
を検索対象にした場合,検索結果のファイルパスにはhoge/fuga/piyo.txt
のようにhoge
ディレクトリの名前が含まれます.
そのまま7z a
コマンドに流すとZIPファイルの圧縮結果に不要な階層(hoge
)が生じます.
そこで--base-directory
オプションで検索結果の表示で起点となるディレクトリを指定し,不要な階層を取り除くようにしました.
最後におまけで,7z l
コマンドを利用して圧縮したファイル一覧を表示するようにしています.
以上です.
ご覧いただきありがとうございました.
-
今回の方法では全ての隠しファイルを取り除いてZIPファイルを作成します.隠しファイルも含めてZIPファイルを作成する場合は,
.DS_Store
等の不要なファイルをピンポイントに取り除くような別の方法を利用してください. ↩ -
macOSはUTF-8,WindowsはShift-JISを利用. ↩
-
p7zipのシェルスクリプト上での実行コマンドは
7z
です. ↩ -
参考:https://pc.watch.impress.co.jp/docs/topic/feature/1513517.html ↩
-
-H
オプションを加えることで隠しファイルを検索対象に含めることができます. ↩ -
fd
のオプションには-x
(小文字)と-X
(大文字)があります.どちらも検索結果に指定したコマンドを実行しますが,小文字だと「検索結果に対して個別に処理」,大文字だと「検索結果に対してバッチ処理」です. ↩