tarよりzipコマンドをつけんかい!

どーでもいい記録です。

長年Windows標準のファイル圧縮・解凍ツールはCAB形式のファイルでした。今もそうですが・・・。そのため、cab形式のファイルを作成したり(makecab.exe)や解凍したり(expand.exe)するコマンドが標準であります。また、GUIシェルであるWindowsエクスプローラは標準でcab形式のファイルをフォルダとして扱えるようになってます。

・・・で、最近 ssh,curl,tarなど、従来では別途どこからか(cygwinやmsysなど)調達してこないといけないようなコマンドがWindows標準で使えるようになりました。特に tar コマンドは・・・それ、いる???? って感じ。

tarコマンドを標準で揃えるぐらいなら、zipコマンドをつけんかい! って思うのです。

Windowsって事実上の世界標準?であるzip形式のコマンドラインツールが付属していません。そうです、コマンドプロンプトでZIP書庫を解凍したり作ったりできないのです。しかし、GUIシェルであるエクスプローラはcabファイルと同じくzip書庫ファイルをフォルダとして扱えるようになってますが、そこまでするなら、なぜzipコマンドを付けないのか・・・ライセンスの問題なのか、何らかの制限があるのかわかりませんが、とっととzipコマンドをつけてほしい。

まぁ、文句を言っててもしょうがないので、代替方法。

■ PowerShellなら可能
コマンドプロンプトでは無理ゲーですが、PowerShellだとZIP形式のファイルを扱えます。

# 書庫展開
>> Expand-Archive -Path <書庫ファイルパス> -DestinationPath <解凍先パス>

# 圧縮
>> Compress-Archive -Path <圧縮するファイルパス(カンマで区切って複数指定可能、ワイルドカード認識)> -DestinationPath <書庫ファイルパス> 

これを 利用してコマンドプロンプトから powershell -Command を実行します。

# sampleディレクトリをそのままzipファイルにします。
>> powershell -Command "Compress-Archive .\sample\ sample.zip"

めんどくさいですが、まぁライトユースには十分です。客先のWindowsデスクトップにリモートデスクトップで接続してデータファイルを圧縮してコピーとかやるとき、zipで固めてからコピーする時とか。好き勝手にツール類をインストールとか、フツーはできないよね?勝手にやったら怒られるわ、セキュリティーの警告が出るわで大変だからね・・・。Windows上でゴニョゴニョする時、できるだけ素のWindowsでできる方法を身に付けとかないと詰みますよね。

まぁ、単に圧縮するだけなら、標準のmakecabの方が便利だけど。分割圧縮書庫にもできるし。メールで1MB制限とかチョーめんどくさい環境でも分割してメールで送れるしね。でも cabファイルって結局Windowsアプリの配布にしか使われなかったよねぇ。まぁマイクロソフト・アレルギーで毛嫌いしてる人多いからねぇ。

最新のSubversionへ

git 使わずんば開発者にあらず。

subversionは既にオワコンらしいが・・・昔から subversionでソースやテキストを管理してきているので、その膨大な量のリポジトリとその履歴をどうやれば git にすんなり移行できるだろうか・・・? と考えた挙句・・・「そのまま subversion でええやん?」という都合のいい囁きに負け・・・しかしまぁ、新しく書く時は git/githubを活用するように習慣を変えました😀

まぁ、それはそれ。

ところで WSL1にはアップデートせずubuntu 1804をそのまま使っているんですが、いかんせん apt でインストールできるパッケージのバージョンがとても古い。subversionだと、バージョンが 1.9という古さ。 今の最新って確か1.14。で、さがせばどこかのAPTリポジトリがあるんでしょうけど、メンドクサイのでソースからビルドすることにした。その備忘録です。

WSL1/ubuntu1804だと依存関係でいろいろ入れないといけないらしく、試行錯誤した結果、以下のシェルスクリプトに落ち着いた。

いろいろ問題が出てきそうなので、aptでインストールしたsubversionを削除することにした。これでやっと TortoiseSVNのsubversionとバージョンが一致した。

CMDとBashと変数展開と・・・

備忘録。

CUIではほとんど WSL1/ubuntu を使っています。WSL2の方が実行パフォーマンスはいいんでしょうけど・・・。

WSL1メインとはいいつつ、コマンドプロンプト(cmd.exe)を全く使わない・・・ということはない。たとえばタスクスケジューラに仕事をしてもらいたい処理は バッチファイル(CMDファイル)に書いて渡す方が何かとトラブルは少なくなりますし。
bitlockerで暗号化しているVHDファイルのマウント処理とかをWindowsのスタートアップスクリプトに登録したりとか、ログオン/ログアウトスクリプトに、後始末するスクリプトとか・・・Windowsのサービスを制御したりとか、コンピュータ名とIPアドレスの対応を調べたりとか、IPのルーティングを変えたりとか、やっぱりcmdファイル(バッチファイル)じゃないと不便なこともあります。

Powershellもありますが・・・ps1ファイルの実行がデフォルトでブロックされているので他所のPCで手軽に動かせない・・・とか、なんかイマイチです。

bashでのシェルスクリプトもウェブ開発では必須なので、いろんな処理の自動化スクリプトをちょくちょく書きます。
・・・で、bashとcmdのスクリプトをいったりきたり、色々書く時いつも躓くのは、変数展開の文法・・・要は書き方をよく忘れてしますこと。頭は悪い上、加齢でどんどん記憶力が落ちていく・・・。
あれ、bashのシェルスクリプトのこういう書き方って、バッチファイルではどうやるんだっけ???ということが度々あるので、カンタンな対応・比較表があれば便利だなと思い、メモついでに書いておく。

最低限こんだけ覚えてればなんとかなる・・・かもしれない。

  bash cmd
1行目 #!/bin/bash @echo off
変数代入 hoge=”This is a sample” SET hoge=This is a sample
変数参照 echo $hoge or echo ${hoge} echo %hoge%
入力 echo -n “please input: ”
read hoge
echo $hoge
SET /P hoge=please input:
echo %hoge%
文字列置換 hoge=”this is my appple pen”
echo ${hoge//this/that}
SET hoge=this is my appple pen
echo %hoge:this=that%
部分文字列 hoge=”this is my appple pen”
echo ${hoge:8:2}
echo ${hoge:8}
SET hoge=this is my appple pen
echo %hoge:~8,2%
echo %hoge:~8%
パス分解
パス
ベース名
拡張子
ファイル名
echo $0
echo ${0%/*}
filename=${0##*/}; echo ${filename%.*}
echo ${0##*.}
echo ${0##*/}
echo %0
echo %~dp0
echo %~n0
echo %~x0
echo %~nx0
日付時刻
乱数(簡易)
echo $(date)
echo $RANDOM
echo %DATE% %TIME%
echo %RANDOM%
IF-ELSE文 if [ expression ] ; then
 …
else
 …
fi
if expression (
 command1
 command2
  ….
) else (
 command3
 command4
 …
)
ループ(while) while [ expression ]
do
 …
done
loop:

if expresssion goto loop
※gotoで代替

間違いは随時修正中。思いついたら随時追加中。

ロック画面のスポットライト画像をコピーしてデスクトップにも流用させたい

ロック画面は何にしてますか?僕は設定でWindowsスポットライトにしてます。
これ、たぶんBingから定期的にダウンロードしてロック画面にスライドショー的に表示していると思うんだけど、なぜかログイン後のデスクトップの背景の設定でWindowsスポットライトの選択肢がないんですよねぇ。

Microsoft Storeで壁紙系のアプリを探せばたぶんあると思いますが、たぶんに要らん機能がくっついてきたり個人情報が抜かれたりと面倒なのでやっぱり自分でなんとかするのが基本です。そうです、信じられるのは唯一自分なのです(笑)

Windowsスポットライトで使用される画像ファイルは、
%LOCALAPPDATA%\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Assets
に保存されているようです。拡張子がないので判別はできませんが、概ね400KB以上のファイルサイズのファイルが該当する画像で、任意のフォルダにコピーして拡張子.JPGでリネームすれば使いまわせます。ライセンスとか分からんが、どこぞに配布するわけではないので大丈夫でしょう。

定期的にピクチャフォルダにコピーすればいいんですが・・・いちいちフォルダ開いてファイルを選別してコピーしてリネームして・・・うわぁぁぁあーーーーーーん、超絶メンドクセーーーーーーー。
さらに、バックグラウンドでダウンロードされる画像ファイルには縦長と横長がごちゃまぜになっている。縦長の画像は不要なので、これも選別項目です。さらにメンドクサイ。

UNIX系のOSなら find コマンドやらimagemagickを駆使してシェルスクリプト化すればいいんですが・・・。
PowerShellを使えばできそうですけど、んーーーー、C#で組んだ方が早ぇよ。。。ということで、組んでみる。

ファイルサイズを判別するのは簡単で、JPEGファイルの高さと幅を取得するのがメンドクサそうですが・・・単純にSOFマーカーから取得することで手抜きします。完璧にしようとすると僕の知識では無理です。

github

JavaScript Map オレオレ拡張

今、かつてないほどJavaScriptと関わっている。
※JavaScriptという名称は正式にはOracleの登録商標で一般的には ECMA Script って事になるんだろうけど、めんどくさいので JavaScript と明記する。あらかじめご了承のほど。

僕のJavaScriptの文法、その他の知識は正直2010年(ES5)ぐらいで止まってる。というのも今持っている知識だけで要求されるほとんどのケースが実現可能だからだ。
もちろんパフォーマンス的な、効率的な・・・というのは棚に上げまくっているんだけど。その当時も ES6 も意識していましたが、まだブラウザでの実装状況が混沌としててInternetExplorerがまだまだ全盛時代だったので、どうしてもすべてのケースで動くように ES5 を強制していた。

今の JavaScript って5~6年前によく見たコーディングスタイルとは全然違いますよね。
ブラウザでホスティングされているJavaScriptで普通にラムダ式が使えるし、変数宣言で var ではなく let を使うことでブロックスコープを意識したコーディングができる。
まぁ、今頃こんなこと書いても、今更感が半端ないんですけどね。

去年から現在進行形で携わっている仕事では、徐々に(少しずつ) ES6 を意識したコーディングを心がけるようになってきました。ほんとに少しずつですけどね💦

余談:(余談ばっかりだが・・・)——————
理由はマイクロソフトが正式に Internet Explorer 及び edge-HTMLをベースにしたEdgeブラウザのサポートを止める、もしくは新規開発しない、事を宣言したから。
残念なことだけど、ITリテラシーの低い人たちからすれば、未だにInternet Explorer がインターネット業界(笑)の標準だと思っている人が結構多い。
マイクロソフトがレガシーブラウザと決別宣言してくれたおかげで、ChromeやFireFox,Chromium版Edgeを強制することが可能になったことが非常に大きい。
———————-

一番意識しているのは(オブジェクト初期化子{}でインスタンスを作る)オブジェクトを連想配列的に使用するのを止めてMap や Set を使うことにしたこと。
MapやSetもかなり以前から実装されているけど、やっぱり InternetExplorer11 では限定的な実装なので使うのも躊躇してた。

Map,Set は非常に便利ですよね。オブジェクトを使用した連想配列では、キー(プロパティー)に文字列ぐらいしか使えない。Mapだとキーに何でも入る。
MDNでの説明だと、頻繁に削除・挿入を繰り返すケースでパフォーマンスが上がるんだそうで。

たいがいの場合、キーには文字列を使うのが大半の用途だと思います。DOM要素やオブジェクトもキーにできると思うけど、正直僕には使いどころが分からない。まぁ、思いつくのは コールバック(関数)なんかをためておく用途にするぐらい。それでも、そういう時は Map よりSetを使うし。。。

でも特にブラウザ上でDOMとか扱っていると、やっぱりプレーンなオブジェクトの方がコーディングが楽な時もある。ので、Map.prototype空間にオレオレMap拡張メソッドを追加して使うことになってくる。

※2020/04/02 ちょっと追記した。

Map.prototype.toPlainObject

たぶん誰もが書いてる・・・と思う、文字通り、文字列をキーにしたMapをオブジェクトに変換する。
最新のブラウザとかだと、Object.fromEntries とかいう Object.entriesの逆動作を行う関数が実装されているので↓は不要なのかも。

Map.prototype.toPlainObject = function()
{
  var rv = {};
  this.forEach(function(v,k) { 
    if(typeof k === 'string')
      rv[k] = v;
  });
  return rv;
};
// もしくはもっと簡単に・・・
Map.prototype.toPlainObject = function()
{
  return Object.fromEntries(this);
};

Map.from

オブジェクトからMapへの変換は・・・↓でいいのかな? Object.entries は比較的新しめのブラウザしか対応してなくない?

Map.from = function(o)
{
  return new Map(Object.entries(o));
};

Map.prototype.stringify

JSON.stringify のもろパクリですね。toString をオーバーライドすればいいんでしょうけど、そこまでするのは止めましょう。
主に localStorage/SessionStorage へ格納するときに使う。

Map.prototype.stringify = function()
{
  return JSON.stringify(this.toPlainObject());
};

Map.parse

これも JSON.parse のパクリ。JSONのパクリというか、文字列を直接parseするのではなく、一旦オブジェクトにJSON.parseで変換して Map に変換します💦

Map.parse = function(str)
{
  return new Map(Object.entries(JSON.parse(str)));
};

Map.prototype.numIncr/Map.prototype.numDecr

オブジェクトだと、普通にobj.counter++ とか、obj.counter += 10 とかできますよね。。。。
Mapだと一旦 getで取得してsetで更新しないといけません。JavaScriptは演算子を定義もしくはオーバーロードできませんよねぇ。。。。
演算子のオーバーロードは混乱の元になるので極力やっちゃいけない、ってC++の時言われてたな・・・。今もそうなのかなぁ。。。

Map.prototype.numIncr = function(key,delta)
{
  if(typeof delta !== 'number' || delta == 0)
    delta = 1;

  var value = this.get(key);
  if(typeof value === 'number')
  {
    value += delta;
    this.set(key,value);
  } 
  return this;
};
Map.prototype.numDecr = function(key,delta)
{
  if(typeof delta !== 'number' || delta == 0)
    delta = 1;

  return this.numIncr(key,-1 * delta);
};

なんか、Mapの良さ(キーはなんでもOK)を殺してしまうようなものばかりだな。。。キーをstringに限定するようなものあればな~・・・とは思いますが、型が強制されない言語だと難しい。

ざっとよく使うものを列挙しました。自分がコピペできるように💦
ここまで書いてて、気づいたのは・・・var使いすぎ問題! ついつい癖で var って書いてしまうんす。
ラムダ式もイマイチ好きになれない記法だったりします。 C#だと当たり前のよう書くんですけどね。。。好き嫌いというより単に癖なのかも。