サポンテ 勉強ノート

サポンテの勉強ノート・読書メモなどを晒します。

正規表現に一致する名前の最新ファイルを開く【Windows/PowerShell】

はじめに

 サポンテは特定のフォルダに、日付ファイル名の日誌のようなものを作っています。気付いたことがあったらすぐ書き記しているのですが、その都度エクスプローラーでフォルダまで移動してファイルを開くのが煩わしく感じます。

 どうせ最新のファイルだけ開ければいいので、フォルダから最新のファイルを開くスクリプトにしようと思いました。

ついでに

 そのような使い方をしているフォルダはいくつかあるので、正規表現でファイル名を指定できるとさらに便利でしょう。ファイル名に日付文字列をつけて管理する手法は JTC で多用されているので、共有すれば他の人の役に立つかもしれません。

使い方

 スクリプトの第一引数にフォルダまでのパスを、第二引数にファイル名の正規表現を指定します。二重引用符は、PowerShell によって変数展開などがされてしまうため正規表現の部分は一重引用符でくくります。

REM 使い方
powershell -ExecutionPolicy Bypass recent_file_open.ps1 "C:\Path\To\Dir" 'Dialy\d{8}\.txt'

スクリプト

# 起動引数を取得する
Param(
    [String]$Dir,
    [String]$Pattern
    )
    
# ファイル一覧を取得する
$files = Get-ChildItem -Path $dir

# 正規表現にマッチするファイル(群)を取得する
$matchFiles = New-Object 'System.Collections.Generic.List[object]'

foreach ($files in $files) {
    if ([regix]::IsMatch($file, $Pattern)) {
        $matchFiles.Add($file)
    }
}

# ファイル作成日時の降順でソートして最新のファイルを取得する
$recentFile = ($matchFiles | Sort-Object -Descending CreationTime | Select-Object -First 1)

# その最新のファイルを開く
Invoke-Item (Join-Path -Path $Dir -ChildPath $recentFile)

リモートデスクトップでログインしているか、直接ログインしているかを判別する【Powershell/Windows】

はじめに

 Windows では、PC にログインする際に必ず使うツールを自動的に起動できる機能(スタートアップ)があります。そんなツール群をサポンテは、スタートアップに直接入れるのではなく、スタートアップに入れたバッチから間接的に起動しています1

 その「必ず使うツール」でも、直接ログインしたときには使いたいけれど、リモートデスクトップでログインした場合には起動してほしくないものがあります。ホスト側だけで使えれば良いツールなどです。

 そんなときに「現在のログインが、直接ログインかリモートログインか」を判別する方法はないものかと思っていて、それがあったので共有します。

やりかた

 サーバーにログインしているユーザーを一覧するコマンド query USER があるので、これをローカルホストに対して実行すれば、端末にログインしているユーザーとその状況がわかります。直接ログイン時は「セッション名」が console になっているので、それを正規表現で抜き出して判定しています。リモートログイン時は rdp- なんとかになっていると思います。

スクリプト

 PowerShell です。

$userName = ($env:USERNAME).ToLower()
$pattern = "^\s*" + $userName + "\s*consele"
$queryUser = (query USER /server:127:0:0:1) -As [String[]]
$IsConsoleLaunch = $False
foreach ($line in $queryUser) {
    $line = $line.ToLower()
    if ([regex]::IsMatch($line, $pattern)) {
        $IsConsoleLaunch = $True
    }
}

If ( $IsConsoleLaunch ) {
    Write-Host "直接ログインです。"
} else {
    Write-Host "リモートログインです。"
}

おわりに

複数のセッション同じユーザーがでログインしている場合、うまく行かない可能性がありますのでご注意ください。


  1. 起動の順序やタイミングを制御したいものもあったので。

git log の出力を XML で [git log output to XML]

はじめに

 サポンテの現在の職場では、Subversion と Git の両方が使われています。svn コマンドには XML 出力のオプションがあり、git コマンドでも同様の出力を得たいという要件が発生しました。

 調べてみると、git log にそんなオプションは無いようです。そのかわり「--pretty オプションがあるから、好きにしたら良いよ!」という英語のサイトが見つかりました。たしかに...。そりゃそうだ。

XML 出力

 svn コマンドが出力する XML のフォーマットに合わせた出力を得るために無理やり一行で書くなら、次のようになるでしょうか。

echo "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"; echo "<log>"; git log --date=format:'%Y/%m/%d %H:%M:%S' --pretty=format:"<logentry revision=\"%h\"><author>%cn</author><date>%cd</date><msg>%s</msg></logentry>"; echo "</log>"

出力結果

 以下のような出力が得られます。

<?xml version="1.0" encoding="UTF-8" ?>
<log>
<logentry revision="5a87af1"><author>サポンテ</author><date>2024/03/17 14:46:50</date><msg>二回目のコミット。</msg></logentry>
<logentry revision="00ee9d9"><author>サポンテ</author><date>2024/03/17 14:28:12</date><msg>最初のコミット。</msg></logentry>
</log>

git log の部分だけ解説

  • %h ... 短いコミットの ID。長いコミット ID にしたい場合は %H を指定。
  • %cn ... コミット者。
  • %cd ... コミット日時。
  • %s ... コミットの題名。本文も入れたいなら %s%n%n%b
  • %n ... 改行。

 日付はそのままだと日本式にならないので --date=format:'%Y/%m/%d %H:%M:%S' を追加しました。

肉食という同調圧力。あるいは躍らされる消費意欲について

 ゲイリー・ヨーロフスキーのスピーチを見てから、その後の生活の中で気づかされたのですが、世の中には「肉」についての広告(広義の肉である動物性食材、卵や乳製品、魚介類含む)が多い。一旦気づいてしまうと、非常に気になります。

 バーガー!

 ステーキ!

 焼肉!

 マグロ!

 大トロ!

 ウニ!

 カニ

 チーズ!


www.youtube.com

 本来、人間の体は草食動物として設計されていて、歴史的にもいっても肉の消費量は近代になってはじめて増加してきた、いうなれば不自然な食生活です。肉食が不自然なものであるなら、肉の消費とは決して必須のものではなく、単に嗜好的なものに過ぎません。

 肉食の増加にともなう工業畜産は、気候変動の主要因です。肉食を直ちに別にやめるべきとは言いませんが、増やす必要はありません。気候危機を回避するために、減らす努力はしなければならないのです。

 これらの広告は、タバコと同様に規制されて然るべきものなのではないでしょうか。

 広告が多いということは、それがつまり「儲けたい」という動機に裏付けられているということ。経済的利益のために、肉の消費を煽る多くの広告が世の中には溢れています。肉食の嗜好は必然でも何でもなく、メディアを通して垂れ流され煽られた消費意欲に過ぎないものだったのです。

 肉食文化の減衰(気候変動対策としての)には「肉税」というアイディアもありますが、その前にまずは広告を規制する方法もあると思います。広告を規制することで肉食の増加に歯止めがかかるなら(かけなければならない)、そうすべきではないでしょうか。

 「表現の自由」という問題もありますが、広告で煽られた購買欲におどらされる消費者の自由とはいったいなんでしょうか。

 今にはじまったことではないかもしれませんが、菜食中心の生活を頑迷に抵抗する人たちがいます。肉食が不自然なもので、健康を損なうことが明らかになっても頑なに肉食に固執する。それはもう宗教じみています。とはいえ、宗教的ではない食文化などないということも、また事実。ある地域では好んで食べている食材が、山を隔てたすぐとなりの地域では見向きもされない。そういう例は少なくありません。そこに科学性はありません。食文化の違いはすべて単なる宗教です。気候危機は、現実の脅威です。宗教上の理由があろうと、現実に脅威があるなら許されるものではないはずです。

正しく改行するラベルを作る【C#】【Visual Studio】【Windows】

はじめに

 タイトルは若干盛り気味ですみません。先日、ラベル内のテキストを改行したい要件があり、調べてすぐに出てきたやり方を試みたところ期待した結果にならなかったため、期待した結果になった方法をここに記しておきます。

すぐに見つかった方法

 すぐに見つかった方法は「AutoSize プロパティを false にする」というものでした。しかしながら試してみると英文の禁則が正しく適用されず、期待した結果が得られませんでした。

続きを読む

macOS の Microsoft Teams が日本語にならない(言語設定が「日本語」になっているのに)

解決方法

 以下のいずれかの方法で設定画面を開きます。

  • ショートカット「Command ⌘ + ,」
  • アプリケーションメニューから「Settings...」
  • 画面右上の「・・・」から「Settings」

 「Appearance and accessibility」を選択して「Language」の項目を確認します。ここが「日本語(日本)」になっているなら、いったん別の物に変えます。たとえば「English(United States)」など。

 変更すると、項目のすぐ下にボタンが現れると思います。ボタン名は「Save and restart」などです。

 すると Teams が再起動し、今度こそ本当に英語版で表示されると思います。もう一度同じ操作をして「日本語(日本)」を選択し、同じく「Save and restart」ボタンをクリックします。

 これで日本語表示になるはずです。

続きを読む

PlantUML のソース圧縮コードを C# で実装した

はじめに

 PlantUML の API に送る圧縮文字列を、C# で作る必要に迫られました。

 ライブラリは以下のようにいろいろ合ったのですが、なんか C# は無さそうだったので作りました。

ソースコード

using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;

namespace ConsoleApp1.Classes
{
    /// <summary>
    /// 文字列を、PlantUML サーバーへのリクエスト用に圧縮する処理クラス。
    /// </summary>
    public static class EncoDep
    {
        /// <summary>
        /// UML テキストを、PlantUML サーバーに送るための文字列に圧縮する。
        /// </summary>
        /// <param name="text">UML 文字列</param>
        /// <returns>圧縮文字列</returns>
        public static string Encode(string text)
        {
            var data = CompressFromStr(text);
            return Encode64(data);
        }

        /// <summary>
        /// バイト(文字)を変換する。
        /// </summary>
        /// <param name="b">変換したい文字</param>
        /// <returns>変換した文字</returns>
        private static byte Encode6bit(byte b)
        {
            if (b < 10)
            {
                return (byte)(48 + b);
            }

            b -= (byte)10;
            if (b < 26)
            {
                return (byte)(65 + b);
            }

            b -= (byte)26;
            if (b < 26)
            {
                return (byte)(97 + b);
            }

            b -= (byte)26;
            if (b == 0)
            {
                return (byte)'-';
            }
            else if (b == 1)
            {
                return (byte)'-';
            }

            return (byte)'?';
        }

        /// <summary>
        /// バイト配列を PlantUML 独自の法則で変換します。
        /// </summary>
        /// <param name="b1">バイナリ1</param>
        /// <param name="b2">バイナリ2</param>
        /// <param name="b3">バイナリ3</param>
        /// <returns>変換した文字列</returns>
        private static string Append3bytes(byte b1, byte b2, byte b3)
        {
            byte c1 = (byte)(b1 >> 2);
            byte c2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
            byte c3 = (byte)(((b2 & 0xf) << 2) | (b3 >> 6));
            byte c4 = (byte)(b3 & 0x3f);

            var list = new List<byte>
            {
                Encode6bit((byte)(c1 & 0x3f)),
                Encode6bit((byte)(c2 & 0x3f)),
                Encode6bit((byte)(c3 & 0x3f)),
                Encode6bit((byte)(c4 & 0x3f))
            };

            return System.Text.Encoding.ASCII.GetString(list.ToArray());
        }

        /// <summary>
        /// バイト配列から base64 に似た PlantUML 独自のエンコードを実施する。
        /// </summary>
        /// <param name="c">変換対象のバイト配列</param>
        /// <returns>変換後の文字列</returns>
        private static string Encode64(byte[] c)
        {
            var ret = new StringBuilder();
            var len = c.Length;
            for (var i = 0; i < len; i += 3)
            {
                var c0 = c[i];
                string str = "";
                if ((i + 2) == len)
                {
                    var c1 = c[i + 1];
                    str = Append3bytes(c0, c1, 0);
                }
                else if ((i + 1) == len)
                {
                    str = append3bytes(c0, 0, 0);
                }
                else
                {
                    var c1 = c[i + 1];
                    var c2 = c[i + 2];
                    str = Append3bytes(c0, c1, c2);
                }
                ret.Append(str);
            }

            return ret.ToString();
        }

        /// <summary>
        /// 文字列を圧縮しバイナリ配列として返します。
        /// </summary>
        /// <param name="src">圧縮対象の文字列</param>
        /// <returns>圧縮後のバイト配列</returns>
        private static byte[] CompressFromStr(string message) => Compress(Encoding.UTF8.GetBytes(message));

        /// <summary>
        /// バイト配列を圧縮します。
        /// </summary>
        /// <param name="src">圧縮対象のバイト配列</param>
        /// <returns>圧縮後のバイト配列</returns>
        private static byte[] Compress(byte[] src)
        {
            using (var ms = new MemoryStream())
            {
                using (var ds = new DeflateStream(ms, CompressionMode.Compress, true)
                {
                    ds.Write(src, 0, src.Length);
                }

                // 圧縮した内容をバイト配列にして取り出す
                ms.Position = 0;
                byte[] comp = new byte[ms.Length];
                ms.Read(comp, 0, comp.Length);

                return comp;
            }
        }
    } /* /class */
} /* /namespace */

参考

PHP から PlantUML を使う PlantUML テキストエンコード C#の標準機能でデータを圧縮・展開する - PG日誌