<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>CLI・シェル環境 on AIによる技術記事 備忘録</title><link>https://ai.hack-le.com/tags/cli%E3%82%B7%E3%82%A7%E3%83%AB%E7%92%B0%E5%A2%83/</link><description>Recent content in CLI・シェル環境 on AIによる技術記事 備忘録</description><generator>Hugo -- gohugo.io</generator><language>ja</language><lastBuildDate>Mon, 02 Nov 2026 09:03:59 +0900</lastBuildDate><atom:link href="https://ai.hack-le.com/tags/cli%E3%82%B7%E3%82%A7%E3%83%AB%E7%92%B0%E5%A2%83/index.xml" rel="self" type="application/rss+xml"/><item><title>EmacsでC-h（ヘルプ）を誤打したときに画面を元の状態へ戻す手順</title><link>https://ai.hack-le.com/emacs%E3%81%A7c-h%EF%BC%88%E3%83%98%E3%83%AB%E3%83%97%EF%BC%89%E3%82%92%E8%AA%A4%E6%89%93%E3%81%97%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AB%E7%94%BB%E9%9D%A2%E3%82%92%E5%85%83%E3%81%AE%E7%8A%B6%E6%85%8B/</link><pubDate>Sun, 25 Oct 2026 22:21:46 +0900</pubDate><guid>https://ai.hack-le.com/emacs%E3%81%A7c-h%EF%BC%88%E3%83%98%E3%83%AB%E3%83%97%EF%BC%89%E3%82%92%E8%AA%A4%E6%89%93%E3%81%97%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AB%E7%94%BB%E9%9D%A2%E3%82%92%E5%85%83%E3%81%AE%E7%8A%B6%E6%85%8B/</guid><description>&lt;p&gt;Emacsの操作中に &lt;code&gt;C-h&lt;/code&gt; を誤って押してしまい、意図せずヘルプ機能に入ってしまうケースは珍しくありません。この状況で混乱が生じやすい根本的な理由は、Emacsが現在 &lt;strong&gt;キー入力の待機中&lt;/strong&gt; なのか、それともすでに &lt;strong&gt;ヘルプ画面が展開された後&lt;/strong&gt; なのかによって、復帰に必要な操作のレイヤーが異なる点にあります。現在の状態を正しく判別できれば、迷わず元の編集状態へ復帰できます。&lt;/p&gt;&#10;&lt;h2 id="キー入力待ちの状態から中断する"&gt;キー入力待ちの状態から中断する&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;C-h&lt;/code&gt; を押した直後、画面最下部のミニバッファに &lt;code&gt;C-h-&lt;/code&gt; と表示されて後続のキー入力を待っている段階では、ヘルプのウィンドウ自体はまだ開かれていません。この状態はEmacsがコマンドの追加入力を受け付けている途中にすぎないため、キーシーケンスの中断コマンドを実行します。&lt;/p&gt;&#10;&lt;p&gt;ここで使用するのが &lt;strong&gt;&lt;code&gt;C-g&lt;/code&gt;&lt;/strong&gt; （&lt;code&gt;keyboard-quit&lt;/code&gt;）です。&lt;code&gt;C-g&lt;/code&gt; を入力すると進行中のコマンド受付が直ちに破棄され、ミニバッファに &lt;code&gt;Quit&lt;/code&gt; と表示されて元のバッファの編集状態に復帰します。&lt;/p&gt;&#10;&lt;h2 id="ヘルプ画面が表示された後に元の配置へ戻す"&gt;ヘルプ画面が表示された後に元の配置へ戻す&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;C-h&lt;/code&gt; に続いて何らかのキーを押してしまい、ウィンドウが2分割されて &lt;code&gt;*Help*&lt;/code&gt; バッファが展開された場合は、キー入力の中断ではなくウィンドウのレイアウトを戻す処理が必要になります。この段階では、カーソル（ポイント）がどちらのウィンドウに存在するかによって選択する操作が変わります。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;ヘルプバッファ側にカーソルがある場合&lt;/strong&gt;: &lt;strong&gt;&lt;code&gt;q&lt;/code&gt;&lt;/strong&gt; （&lt;code&gt;quit-window&lt;/code&gt;）を押します。ヘルプ表示用のモードでは &lt;code&gt;q&lt;/code&gt; にウィンドウを閉じて直前の配置に戻す動作が割り当てられているため、1ストロークで元の状態に復帰します。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;元の編集バッファ側にカーソルがある場合&lt;/strong&gt;: &lt;strong&gt;&lt;code&gt;C-x 1&lt;/code&gt;&lt;/strong&gt; （&lt;code&gt;delete-other-windows&lt;/code&gt;）を押します。現在カーソルが置かれているウィンドウ以外の分割画面が一括で非表示となり、編集画面が再び単一の全画面表示に戻ります。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;編集側からヘルプバッファを経由して閉じたい場合&lt;/strong&gt;: ウィンドウ間を移動する &lt;strong&gt;&lt;code&gt;C-x o&lt;/code&gt;&lt;/strong&gt; （&lt;code&gt;other-window&lt;/code&gt;）でヘルプ側へカーソルを移してから &lt;code&gt;q&lt;/code&gt; を入力することでも同様に復帰できます。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="状態の識別と混乱を防ぐ要点"&gt;状態の識別と混乱を防ぐ要点&#10;&lt;/h2&gt;&lt;p&gt;操作に迷いが生じる原因は、キーシーケンスの破棄である &lt;strong&gt;入力の中断&lt;/strong&gt; と、画面レイアウトの復元である &lt;strong&gt;ウィンドウの破棄&lt;/strong&gt; という2つの異なる処理を混同しやすい点にあります。&lt;/p&gt;&#10;&lt;p&gt;画面が分割される前の入力待ちであれば &lt;strong&gt;&lt;code&gt;C-g&lt;/code&gt;&lt;/strong&gt; 、画面が分割された後であれば &lt;strong&gt;&lt;code&gt;q&lt;/code&gt;&lt;/strong&gt; または &lt;strong&gt;&lt;code&gt;C-x 1&lt;/code&gt;&lt;/strong&gt; というように、Emacsの画面状態に応じたキーを選択することが確実な復帰に繋がります。&lt;/p&gt;&#10;</description></item><item><title>rsyncで「IO error encountered — skipping file deletion」が発生した原因と対処法</title><link>https://ai.hack-le.com/rsync%E3%81%A7%E3%80%8Cio-error-encountered-skipping-file-deletion%E3%80%8D%E3%81%8C%E7%99%BA%E7%94%9F%E3%81%97%E3%81%9F%E5%8E%9F%E5%9B%A0%E3%81%A8%E5%AF%BE%E5%87%A6%E6%B3%95/</link><pubDate>Sun, 30 Aug 2026 12:37:13 +0900</pubDate><guid>https://ai.hack-le.com/rsync%E3%81%A7%E3%80%8Cio-error-encountered-skipping-file-deletion%E3%80%8D%E3%81%8C%E7%99%BA%E7%94%9F%E3%81%97%E3%81%9F%E5%8E%9F%E5%9B%A0%E3%81%A8%E5%AF%BE%E5%87%A6%E6%B3%95/</guid><description>&lt;p&gt;rsyncを利用して定期的なローカルバックアップスクリプトを運用している際、転送処理中にエラーが発生して一部のファイル同期および削除処理がスキップされるトラブルに遭遇しました。今回はその原因の特定と、安全にスクリプトを修正して正常終了させるまでの手順をまとめます。&lt;/p&gt;&#10;&lt;h2 id="エラーの発生状況と原因"&gt;エラーの発生状況と原因&#10;&lt;/h2&gt;&lt;p&gt;バックアップスクリプトを実行したところ、転送の途中で以下のようなメッセージが出力されました。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IO error encountered -- skipping file deletion&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rsync: &lt;span class="o"&gt;[&lt;/span&gt;sender&lt;span class="o"&gt;]&lt;/span&gt; opendir &lt;span class="s2"&gt;&amp;#34;/path/to/app1/data/db&amp;#34;&lt;/span&gt; failed: Permission denied &lt;span class="o"&gt;(&lt;/span&gt;13&lt;span class="o"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rsync: &lt;span class="o"&gt;[&lt;/span&gt;sender&lt;span class="o"&gt;]&lt;/span&gt; opendir &lt;span class="s2"&gt;&amp;#34;/path/to/app2/db-data&amp;#34;&lt;/span&gt; failed: Permission denied &lt;span class="o"&gt;(&lt;/span&gt;13&lt;span class="o"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rsync error: some files/attrs were not transferred &lt;span class="o"&gt;(&lt;/span&gt;see previous errors&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;code 23&lt;span class="o"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この現象には2つの連動した原因があります。&lt;/p&gt;&#10;&lt;p&gt;直接的な原因は、コンテナ等で稼働しているアプリケーション（データベースなど）のデータディレクトリに対して、一般ユーザー権限で実行していたrsyncがアクセスできず、&lt;strong&gt;Permission denied&lt;/strong&gt; となったことです。コンテナ内のプロセスが専用のUIDでディレクトリを作成しているため、一般ユーザーの読み取り権限が制限されていました。&lt;/p&gt;&#10;&lt;p&gt;間接的なエラーである &lt;code&gt;IO error encountered -- skipping file deletion&lt;/code&gt; は、rsyncが備えている安全機能によるものです。同期元でアクセスエラーや読み込み不可のファイルが発生した場合、rsyncはファイルが削除されたのか、単に読み込めないだけなのかを判別できません。そのため、同期先のファイルを誤って消去してしまわないよう、&lt;code&gt;--delete&lt;/code&gt; オプションによる削除処理を自動的に中断します。&lt;/p&gt;&#10;&lt;h2 id="対処法dbデータディレクトリの除外"&gt;対処法：DBデータディレクトリの除外&#10;&lt;/h2&gt;&lt;p&gt;稼働中のデータベースが持つ生データディレクトリをそのままファイル単位でrsync同期することは、データの整合性が崩れるリスクが高いため推奨されません。データベースのバックアップはダンプファイルを別途出力してそれを同期するのが安全です。&lt;/p&gt;&#10;&lt;p&gt;そのため、今回は読み取り権限のないデータベース関連のディレクトリを &lt;code&gt;--exclude&lt;/code&gt; オプションで明示的に除外する方針をとりました。&lt;/p&gt;&#10;&lt;p&gt;修正前のスクリプトでは、ドライブ直下のシステム用ディレクトリである &lt;code&gt;lost+found&lt;/code&gt; のみを除外していましたが、コンテナのデータディレクトリも除外対象へ追加しました。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rsync -avh --delete --exclude&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;lost+found&amp;#34;&lt;/span&gt; /path/to/source_disk1/ /path/to/backup_disk/disk1/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rsync -avh --delete --exclude&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;lost+found&amp;#34;&lt;/span&gt; /path/to/source_disk2/ /path/to/backup_disk/disk2/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rsync -avh --delete --exclude&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;lost+found&amp;#34;&lt;/span&gt; /path/to/user_data/ /path/to/backup_disk/share/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rsync -avh --delete &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --exclude&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;lost+found&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --exclude&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;app1/data/db&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --exclude&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;app2/db-data&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /path/to/applications/ /path/to/backup_disk/applications/&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;除外パスの指定は、同期元（&lt;code&gt;/path/to/applications/&lt;/code&gt;）からの相対パスで記述します。&lt;/p&gt;&#10;&lt;h2 id="修正後の動作確認"&gt;修正後の動作確認&#10;&lt;/h2&gt;&lt;p&gt;スクリプト修正後に再度実行したところ、アクセス権限エラーや削除スキップの警告は出力されなくなりました。&lt;/p&gt;&#10;&lt;p&gt;実行直後に &lt;code&gt;echo $?&lt;/code&gt; で終了ステータスを確認し、正常終了を示す &lt;strong&gt;0&lt;/strong&gt; が返ってくることを確認して作業完了としました。&lt;/p&gt;&#10;&lt;p&gt;権限エラーを無理やり無視する &lt;code&gt;--ignore-errors&lt;/code&gt; などのオプションに頼るのではなく、不要なディレクトリや整合性の担保できないデータディレクトリを適切に除外することが、堅牢なバックアップ運用につながります。&lt;/p&gt;&#10;</description></item><item><title>Emacsを常にターミナル内（-nw）で起動させる設定とsudo実行時の対策</title><link>https://ai.hack-le.com/emacs%E3%82%92%E5%B8%B8%E3%81%AB%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB%E5%86%85%EF%BC%88-nw%EF%BC%89%E3%81%A7%E8%B5%B7%E5%8B%95%E3%81%95%E3%81%9B%E3%82%8B%E8%A8%AD%E5%AE%9A%E3%81%A8sudo/</link><pubDate>Sat, 22 Aug 2026 17:28:18 +0900</pubDate><guid>https://ai.hack-le.com/emacs%E3%82%92%E5%B8%B8%E3%81%AB%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB%E5%86%85%EF%BC%88-nw%EF%BC%89%E3%81%A7%E8%B5%B7%E5%8B%95%E3%81%95%E3%81%9B%E3%82%8B%E8%A8%AD%E5%AE%9A%E3%81%A8sudo/</guid><description>&lt;p&gt;GUI環境が整っている端末であっても、エディタはターミナル内部で軽快に動かしたいという場面は多くあります。Emacsをターミナル内で起動するには通常 &lt;code&gt;-nw&lt;/code&gt; オプションを付与しますが、コマンドを実行するたびに入力するのは手間がかかります。そこで、常にターミナル内で開くための設定と、&lt;code&gt;sudo&lt;/code&gt; を付与した際にもその挙動を維持する方法、さらに安全に管理者権限で編集するための代替アプローチを整理します。&lt;/p&gt;&#10;&lt;h2 id="常にターミナル内でemacsを起動するエイリアス設定"&gt;常にターミナル内でEmacsを起動するエイリアス設定&#10;&lt;/h2&gt;&lt;p&gt;コマンド入力を省略する最もシンプルな手段は、利用しているシェルの設定ファイル（Bashであれば &lt;code&gt;~/.bashrc&lt;/code&gt;、Zshであれば &lt;code&gt;~/.zshrc&lt;/code&gt;）にエイリアスを登録することです。&lt;/p&gt;&#10;&lt;p&gt;設定ファイルへ以下のように記述します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;emacs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;emacs -nw&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;記述後に &lt;code&gt;source ~/.bashrc&lt;/code&gt; や &lt;code&gt;source ~/.zshrc&lt;/code&gt; を実行して設定を再読み込みすれば、以降は &lt;code&gt;emacs&lt;/code&gt; と入力するだけで自動的に &lt;code&gt;-nw&lt;/code&gt; が付与された状態で起動するようになります。なお、稀にGUIウィンドウでEmacsを立ち上げたい状況が発生した場合は、コマンドの先頭にバックスラッシュを付与して &lt;code&gt;\emacs&lt;/code&gt; と実行することで、登録したエイリアスを一時的に無効化して起動できます。&lt;/p&gt;&#10;&lt;h2 id="sudo実行時にエイリアスを展開させる工夫"&gt;sudo実行時にエイリアスを展開させる工夫&#10;&lt;/h2&gt;&lt;p&gt;一般ユーザー権限ではエイリアスによって意図通りに動作しますが、システムファイルの編集などで &lt;code&gt;sudo emacs&lt;/code&gt; を実行した途端、ふたたびGUI版が立ち上がってしまう問題に直面します。これは、&lt;code&gt;sudo&lt;/code&gt; コマンドがデフォルトではシェルのエイリアスを展開せず、後続の引数をそのまま実行ファイル名として解釈するためです。&lt;/p&gt;&#10;&lt;p&gt;この仕様を回避するには、シェル設定ファイルに以下のエイリアスを追加します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;sudo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;sudo &amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ポイントは、末尾に&lt;strong&gt;半角スペース&lt;/strong&gt;を含めている点です。多くのシェルには「エイリアス展開後の文字列が空白で終わっている場合、続く次の単語に対してもエイリアス展開を試みる」という仕様が備わっています。これを利用することで、&lt;code&gt;sudo emacs&lt;/code&gt; と入力した際にも直後の &lt;code&gt;emacs&lt;/code&gt; が &lt;code&gt;emacs -nw&lt;/code&gt; へと正常に展開されるようになります。&lt;/p&gt;&#10;&lt;h2 id="安全に管理者権限で編集するsudoeditの活用"&gt;安全に管理者権限で編集するsudoeditの活用&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;sudo emacs&lt;/code&gt; でエイリアスを効かせる方法のほかに、セキュリティの観点から推奨される手段として &lt;code&gt;sudoedit&lt;/code&gt;（または &lt;code&gt;sudo -e&lt;/code&gt;）の利用が挙げられます。&lt;code&gt;sudo emacs&lt;/code&gt; はEmacsプロセス全体をroot権限で動作させるため、万一エディタ内で意図しない処理が走った際のリスクが高まります。対して &lt;code&gt;sudoedit&lt;/code&gt; は、対象ファイルの複製を一時ファイルとして一般ユーザー権限のエディタで編集し、保存・終了時にのみ管理者権限で元のファイルへ上書きする仕組みをとっています。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;sudoedit&lt;/code&gt; で起動するエディタをEmacsのCUIモードにするには、シェルの設定ファイルで環境変数を指定します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;EDITOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;emacs -nw&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;VISUAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;emacs -nw&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;設定反映後は、&lt;code&gt;sudoedit /path/to/file&lt;/code&gt; のようにファイルを指定して編集します。root権限でのエディタ直接実行を避けつつ、普段と同じターミナル環境のEmacsで安全にシステムファイルを更新できます。&lt;/p&gt;&#10;</description></item><item><title>macOS 14.8.3におけるスクリーンショット保存先とファイル形式のJPG変更手順</title><link>https://ai.hack-le.com/macos-14-8-3%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%E4%BF%9D%E5%AD%98%E5%85%88%E3%81%A8%E3%83%95%E3%82%A1%E3%82%A4/</link><pubDate>Sat, 31 Jan 2026 16:55:41 +0900</pubDate><guid>https://ai.hack-le.com/macos-14-8-3%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%E4%BF%9D%E5%AD%98%E5%85%88%E3%81%A8%E3%83%95%E3%82%A1%E3%82%A4/</guid><description>&lt;p&gt;macOSの標準機能であるスクリーンショットは、初期設定において「デスクトップ」を保存先とし、ファイル形式には「PNG」が採用されている。本記事では、保存先の変更とファイル形式の変更について記述する。&lt;/p&gt;&#10;&lt;h2 id="環境"&gt;環境&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;strong&gt;項目&lt;/strong&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;strong&gt;内容&lt;/strong&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;OSバージョン&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;macOS 14.8.3&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;使用ツール&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ターミナル (Terminal.app)、スクリーンショットアプリ&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;目的&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ファイルサイズの軽量化およびディレクトリ管理の整理&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="スクリーンショットアプリによる直感的な保存場所の変更"&gt;スクリーンショットアプリによる直感的な保存場所の変更&#10;&lt;/h2&gt;&lt;p&gt;macOSには標準でスクリーンショットを管理するための専用インターフェースが備わっており、GUI操作のみで保存場所の変更が可能である。&lt;/p&gt;&#10;&lt;p&gt;キーボードの &lt;code&gt;Command&lt;/code&gt; + &lt;code&gt;Shift&lt;/code&gt; + &lt;code&gt;5&lt;/code&gt; を同時に押下し、画面下部にスクリーンショットツールバーを表示させる。このツールバー内に存在する「オプション」メニューをクリックすることで、保存先の候補が表示される。&lt;/p&gt;&#10;&lt;h2 id="ターミナルを利用したファイル形式のjpg化と詳細設定"&gt;ターミナルを利用したファイル形式のJPG化と詳細設定&#10;&lt;/h2&gt;&lt;p&gt;ファイル形式をPNGからJPGへ変更し、さらに保存場所をコマンドラインから厳密に指定するには、ターミナルでの操作が最も確実である。まず、LaunchpadやSpotlightから「ターミナル」を起動する。ファイル形式をJPGに変更するには、以下のコマンドを入力し、実行する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;defaults write com.apple.screencapture &lt;span class="nb"&gt;type&lt;/span&gt; jpg&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドは、システムの環境設定ファイルを書き換えるものであり、&lt;code&gt;type&lt;/code&gt; の後には &lt;code&gt;png&lt;/code&gt;、&lt;code&gt;pdf&lt;/code&gt;、&lt;code&gt;tiff&lt;/code&gt;、&lt;code&gt;gif&lt;/code&gt; など任意の拡張子を指定できる。次に、保存場所もコマンドで指定したい場合は、以下の書式を用いる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;defaults write com.apple.screencapture location ~/Pictures/Screenshots&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここで使用している &lt;code&gt;~/Pictures/Screenshots&lt;/code&gt; は一例であり、ユーザの環境に合わせて任意のパスに変更することが可能である。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;defaults&lt;/code&gt; コマンドを使用して設定を書き換えただけでは、システムに即座に変更が反映されない場合がある。設定を有効化するためには、macOSのUI管理プロセスである &lt;code&gt;SystemUIServer&lt;/code&gt; を再起動させる必要がある。以下のコマンドを実行することで、Mac本体を再起動させることなく新しい設定を適用できる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;killall SystemUIServer&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コマンドの実行後、実際に &lt;code&gt;Command&lt;/code&gt; + &lt;code&gt;Shift&lt;/code&gt; + &lt;code&gt;3&lt;/code&gt; （全画面撮影）や &lt;code&gt;Command&lt;/code&gt; + &lt;code&gt;Shift&lt;/code&gt; + &lt;code&gt;4&lt;/code&gt; （範囲指定撮影）を行い、動作を検証する。指定した保存先にファイルが出力されていること、およびファイルの拡張子が &lt;code&gt;.jpg&lt;/code&gt; になっていることを情報ウィンドウ（&lt;code&gt;Command&lt;/code&gt; + &lt;code&gt;I&lt;/code&gt;）で確認する。&lt;/p&gt;&#10;&lt;p&gt;もし設定を元に戻したい場合は、形式を &lt;code&gt;png&lt;/code&gt; に指定し、同様の手順で &lt;code&gt;killall&lt;/code&gt; コマンドを実行すればよい。&lt;/p&gt;&#10;</description></item><item><title>Webブラウザでシェルにアクセスする Shell In A Box のセットアップ備忘録</title><link>https://ai.hack-le.com/web%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%A7%E3%82%B7%E3%82%A7%E3%83%AB%E3%81%AB%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%99%E3%82%8B-shell-in-a-box-%E3%81%AE%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2/</link><pubDate>Mon, 15 Dec 2025 12:34:40 +0900</pubDate><guid>https://ai.hack-le.com/web%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%A7%E3%82%B7%E3%82%A7%E3%83%AB%E3%81%AB%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%99%E3%82%8B-shell-in-a-box-%E3%81%AE%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2/</guid><description>&lt;h2 id="目的と再現環境"&gt;目的と再現環境&#10;&lt;/h2&gt;&lt;p&gt;Webブラウザを経由してサーバーまたはローカルマシンにセキュアにアクセスできるターミナル環境を構築することは、リモートワークフローや簡易的なサーバー管理において利便性が高い。本記事は、WebベースのSSHクライアントである Shell In A Box (SIA) をmacOS上にセルフホストし、LAN内の他のPCからアクセス可能にするまでの具体的な手順を記録することを目的とする。&lt;/p&gt;&#10;&lt;h3 id="前提となる再現環境"&gt;前提となる再現環境&#10;&lt;/h3&gt;&lt;p&gt;本記事で解説する手順は、以下の環境を前提とし、Macをホストマシンとして使用する。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;ホストOS&lt;/strong&gt;: macOS (Homebrewがインストールされていること)&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;クライアント環境&lt;/strong&gt;: LAN内の任意のPCにインストールされたWebブラウザ&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;ツール&lt;/strong&gt;: Shell In A Box (SIA)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;この手順は、特別な外部サービスを必要とせず、Homebrewが利用できる環境であればすぐに再現できる。&lt;/p&gt;&#10;&lt;h2 id="shell-in-a-boxのインストールと基本的な起動"&gt;Shell In A Boxのインストールと基本的な起動&#10;&lt;/h2&gt;&lt;p&gt;Shell In A Box を使用可能にする最初のステップは、MacのパッケージマネージャーであるHomebrewを利用したツールのインストールである。HomebrewはmacOS上でUNIXツールやパッケージを簡単に管理するためのデファクトスタンダードであり、この手順を大幅に簡略化する。&lt;/p&gt;&#10;&lt;p&gt;Homebrewが導入されていることを確認した後、ターミナルで以下のコマンドを実行し、Shell In A Boxをインストールする。&lt;/p&gt;&#10;&lt;p&gt;Bash&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;brew install shellinabox&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;インストール完了後、Shell In A Box デーモン（&lt;code&gt;shellinaboxd&lt;/code&gt;）を起動する。LAN内での利用を想定する場合、アクセス制御とセキュリティのため、簡易テスト用の &lt;code&gt;-t&lt;/code&gt; オプションではなく、ログインプロンプトを表示するデフォルトモードで起動することが推奨される。&lt;/p&gt;&#10;&lt;p&gt;Bash&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;shellinaboxd&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドを実行すると、Shell In A BoxはデフォルトでTCPポート &lt;code&gt;4200&lt;/code&gt; を使用して接続待ちの状態となる。この際、ターミナルには特にメッセージが表示されないことが多い。この状態でMac上のWebブラウザ（例: Chrome, Safari）を開き、&lt;code&gt;http://localhost:4200/&lt;/code&gt; にアクセスすることで、ログインプロンプトが表示されることを確認できる。ログイン認証には、ホストマシン（Mac）の&lt;strong&gt;ユーザー名とパスワード&lt;/strong&gt;を使用する。これにより、ブラウザ内でMacのターミナルを操作する準備が整う。この基本的な起動により、ローカルマシンでの動作が確認でき、次のステップであるLAN内アクセスへの布石となる。&lt;/p&gt;&#10;&lt;h2 id="lan内アクセスを可能にする設定と手順"&gt;LAN内アクセスを可能にする設定と手順&#10;&lt;/h2&gt;&lt;p&gt;Shell In A Boxは、デフォルトでMacのすべてのネットワークインターフェースからの接続を待ち受ける設定になっている。そのため、LAN内の他のPCからアクセスを可能にするために必要なのは、ホストであるMacのローカルIPアドレスを確認することのみである。これにより、MacのWebブラウザだけでなく、ネットワークを介した任意のデバイスからシェルにアクセスすることが可能となる。&lt;/p&gt;&#10;&lt;p&gt;まず、Shell In A BoxにアクセスするためのホストとなるMacのプライベートIPアドレスを確認する。これは「システム設定」や「システム環境設定」の「ネットワーク」セクションから確認可能である。例えば、IPアドレスが &lt;code&gt;192.168.1.10&lt;/code&gt; であると仮定する。このIPアドレスは、LAN内でのみ有効なアドレスであり、外部インターネットからのアクセスには使用されない。&lt;/p&gt;&#10;&lt;p&gt;次に、LAN内の他のPCのWebブラウザを開き、以下の形式のURLを入力してアクセスする。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;http://&lt;span class="o"&gt;[&lt;/span&gt;MacのIPアドレス&lt;span class="o"&gt;]&lt;/span&gt;:4200/&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;具体例として、IPアドレスが &lt;code&gt;192.168.1.10&lt;/code&gt; の場合、アクセスURLは &lt;code&gt;http://192.168.1.10:4200/&lt;/code&gt; となる。このURLにアクセスすると、ブラウザにShell In A Boxのログイン画面が表示される。ここで、ホストMacのユーザー名とパスワードを入力することで、LAN内の任意のPCからMacのシェル環境を操作することが可能となる。この方法は、Webベースのサービスとしてシェルを提供するため、クライアント側に追加のSSHクライアントソフトウェアをインストールする必要がないという利点がある。このプロセス全体を通じて、セキュリティを確保するため、&lt;strong&gt;パスワード認証&lt;/strong&gt;が必須となることに留意すべきである。&lt;/p&gt;&#10;&lt;h2 id="pc起動時の自動起動設定"&gt;PC起動時の自動起動設定&#10;&lt;/h2&gt;&lt;p&gt;Shell In A Boxの利便性を最大化するには、ホストマシン（Mac）の起動時に自動的にサービスを開始させることが重要である。macOSでは、ユーザーログイン後にサービスを自動起動させるために、標準機能である &lt;code&gt;launchd&lt;/code&gt; とその設定ファイル（&lt;code&gt;.plist&lt;/code&gt; ファイル）を利用する。これにより、手動で毎回ターミナルで起動コマンドを実行する手間を省くことができる。&lt;/p&gt;&#10;&lt;p&gt;まず、以下の構造を持つプロパティリスト（&lt;code&gt;plist&lt;/code&gt;）ファイルをホームディレクトリ内の適切な場所に作成する。ファイル名は慣例に従い、&lt;code&gt;com.shellinabox.server.plist&lt;/code&gt; とする。保存場所はユーザーごとのサービス定義を格納するディレクトリである &lt;code&gt;~/Library/LaunchAgents/&lt;/code&gt; である。&lt;/p&gt;&#10;&lt;p&gt;XML&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ~/Library/LaunchAgents/com.shellinabox.server.plist&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;dict&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;key&amp;gt;Label&amp;lt;/key&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;string&amp;gt;com.shellinabox.server&amp;lt;/string&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;key&amp;gt;ProgramArguments&amp;lt;/key&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;array&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;string&amp;gt;/usr/local/bin/shellinaboxd&amp;lt;/string&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;/array&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;key&amp;gt;RunAtLoad&amp;lt;/key&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;true/&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;key&amp;gt;KeepAlive&amp;lt;/key&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;true/&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;key&amp;gt;UserName&amp;lt;/key&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;string&amp;gt;（Macのユーザー名）&amp;lt;/string&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;key&amp;gt;StandardErrorPath&amp;lt;/key&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;string&amp;gt;/tmp/shellinabox.err&amp;lt;/string&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;key&amp;gt;StandardOutPath&amp;lt;/key&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;string&amp;gt;/tmp/shellinabox.out&amp;lt;/string&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/dict&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;注意点として&lt;/strong&gt;、&lt;code&gt;&amp;lt;key&amp;gt;UserName&amp;lt;/key&amp;gt;&lt;/code&gt; の値には、実際にShell In A Boxを実行するMacのユーザー名を正確に記述する必要がある。&lt;/p&gt;&#10;&lt;p&gt;ファイルを作成した後、ターミナルに戻り、&lt;code&gt;launchctl&lt;/code&gt; コマンドを使用してサービスをシステムに登録し、ロード（起動）する。&lt;/p&gt;&#10;&lt;p&gt;Bash&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;launchctl load ~/Library/LaunchAgents/com.shellinabox.server.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この操作により、Shell In A Boxのサービスが即座に起動し、かつ、次回以降のMacの再起動時やログイン時に自動的に実行されるようになる。この設定によって、Webブラウザを開くだけで、常にLAN内からMacのシェル環境にアクセスできる状態が維持され、特にWordPress管理CLIの実行などの用途において、シームレスな作業環境が提供されるのである。&lt;/p&gt;&#10;</description></item><item><title>bashでターミナル間の履歴を共有する方法</title><link>https://ai.hack-le.com/bash%E3%81%A7%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB%E9%96%93%E3%81%AE%E5%B1%A5%E6%AD%B4%E3%82%92%E5%85%B1%E6%9C%89%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</link><pubDate>Thu, 27 Nov 2025 14:50:56 +0900</pubDate><guid>https://ai.hack-le.com/bash%E3%81%A7%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB%E9%96%93%E3%81%AE%E5%B1%A5%E6%AD%B4%E3%82%92%E5%85%B1%E6%9C%89%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</guid><description>&lt;p&gt;bash の履歴は通常、各ターミナルが独立して管理しており、複数のウィンドウを開いて作業していると、過去に実行したコマンドが別のターミナルに反映されず不便である。この問題は、bash が履歴ファイル（一般に &lt;code&gt;~/.bash_history&lt;/code&gt;）を読み書きするタイミングが限られていることに起因する。&lt;/p&gt;&#10;&lt;p&gt;デフォルトでは、ターミナル終了時に履歴が書き込まれる仕様であり、そのためリアルタイムの共有は行われない。本稿では、この挙動を変更し、&lt;strong&gt;どのターミナルからも最新履歴を利用できる環境を構築する方法&lt;/strong&gt;について解説する。&lt;/p&gt;&#10;&lt;h2 id="履歴共有の仕組み"&gt;履歴共有の仕組み&#10;&lt;/h2&gt;&lt;p&gt;bash に対して「履歴をリアルタイムに書き込み、かつ常に読み込む」ことを明示的に指示する。bash には &lt;code&gt;PROMPT_COMMAND&lt;/code&gt; という特別な環境変数が存在し、これはプロンプトが表示される直前に bash が必ず実行するコマンド列を定義する。&lt;/p&gt;&#10;&lt;p&gt;履歴同期のためには、この仕組みを利用して、直前のコマンドを履歴ファイルに追記する &lt;code&gt;history -a&lt;/code&gt; を実行し、他ターミナルが書き込んだ履歴を読み込む &lt;code&gt;history -n&lt;/code&gt; を実行するという二段構えが必要になる。また、履歴ファイルの内容を上書きせず追記する &lt;code&gt;histappend&lt;/code&gt; を有効にすることで、複数ターミナルが同時に履歴を書いても衝突が起こらない。&lt;/p&gt;&#10;&lt;h2 id="実装方法"&gt;実装方法&#10;&lt;/h2&gt;&lt;p&gt;履歴共有の設定は &lt;code&gt;.bashrc&lt;/code&gt; に記述することで有効になる。&lt;code&gt;.bashrc&lt;/code&gt; はログインシェルでなくとも読み込まれるため、複数ターミナルで開く通常の対話型シェルの設定として適切である。以下に示す設定を追記すれば、ターミナルを跨いで履歴が共有される。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;shopt&lt;/span&gt; -s histappend&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;PROMPT_COMMAND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;history -a; history -n&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この設定を追加したら、&lt;code&gt;source ~/.bashrc&lt;/code&gt; を実行して反映させる。&lt;/p&gt;&#10;&lt;h2 id="強制同期が必要な場合オプション"&gt;強制同期が必要な場合（オプション）&#10;&lt;/h2&gt;&lt;p&gt;履歴の衝突や順序の乱れが気になるような環境では、より強制的な同期方法として &lt;code&gt;history -c&lt;/code&gt; を併用する設定がある。これは一度メモリ上の履歴を全消去し、その後ファイルから再度読み込むため、最新状態が常に正確に再現される。設定は以下のとおりである。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;PROMPT_COMMAND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;history -a; history -c; history -n&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ただし、この手法は履歴の並びが不自然になりやすいなどの副作用があるため、常用するというよりは、履歴を厳密に同期させたい特定の場面でのみ利用すべきである。&lt;/p&gt;&#10;</description></item><item><title>動画ダウンロードの定番──yt-dlpという万能ツール</title><link>https://ai.hack-le.com/%E5%8B%95%E7%94%BB%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89%E3%81%AE%E5%AE%9A%E7%95%AA%E2%94%80%E2%94%80yt-dlp%E3%81%A8%E3%81%84%E3%81%86%E4%B8%87%E8%83%BD%E3%83%84%E3%83%BC%E3%83%AB/</link><pubDate>Wed, 05 Nov 2025 08:11:15 +0900</pubDate><guid>https://ai.hack-le.com/%E5%8B%95%E7%94%BB%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89%E3%81%AE%E5%AE%9A%E7%95%AA%E2%94%80%E2%94%80yt-dlp%E3%81%A8%E3%81%84%E3%81%86%E4%B8%87%E8%83%BD%E3%83%84%E3%83%BC%E3%83%AB/</guid><description>&lt;p&gt;動画サイトの海を自由に泳ぎたい者にとって、&lt;code&gt;yt-dlp&lt;/code&gt;は最強の羅針盤である。YouTubeをはじめ、無数の配信サイトから動画や音声を自在に取得できるその力は、まるで多言語を理解する通訳のように万能だ。だが、いくら名ツールでも、その使い方を知らなければただの宝の持ち腐れである。本稿では、&lt;code&gt;yt-dlp&lt;/code&gt;の基本的な操作法を一通り押さえ、使いこなすための筋道を記す。&lt;/p&gt;&#10;&lt;h2 id="導入という第一歩"&gt;導入という第一歩&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;yt-dlp&lt;/code&gt;はPython製のツールであり、インストールも簡潔だ。ターミナルで次の一行を叩くだけで始まる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;U&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dlp&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この瞬間、あなたのマシンに強力なダウンローダーが宿る。macOSやLinuxを使っているなら、Homebrew経由での導入も選べる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;brew&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dlp&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;更新も容易であり、常に最新版を保つことが推奨される。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;yt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dlp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;U&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コマンドラインに抵抗を覚える者もいるが、一度慣れればGUIのような視覚的ツールよりもはるかに迅速で正確だ。&lt;/p&gt;&#10;&lt;h2 id="基本動作urlひとつで完結する魔法"&gt;基本動作──URLひとつで完結する魔法&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;yt-dlp&lt;/code&gt;の核心はシンプルな命令にある。対象となる動画URLを指定すれば、それだけでダウンロードが始まる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;yt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dlp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;youtube&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;XXXXXXXXXXX&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;特別なオプションを付けなくとも、自動で最高画質を選択して保存してくれる。まるでソムリエが最適なワインを差し出すように、ユーザーの手を煩わせない。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="音だけを抜き出すという美学"&gt;音だけを抜き出すという美学&#10;&lt;/h2&gt;&lt;p&gt;動画のすべてを欲する必要はない。ときに音声だけで十分なこともある。音楽、講演、ラジオ──それらを純粋な音として残したいなら、次のコマンドが適切だ。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;yt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dlp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;--audio-format mp3 https://www.youtube.com/watch?v=XXXXXXXXXXX&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;-x&lt;/code&gt;は音声抽出を意味し、&lt;code&gt;--audio-format&lt;/code&gt;で形式を指定できる。&lt;code&gt;mp3&lt;/code&gt;のほか、&lt;code&gt;m4a&lt;/code&gt;や&lt;code&gt;wav&lt;/code&gt;なども選択可能だ。映像を削ぎ落とし、声や音だけを抽出する行為には、ある種の潔さがある。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="整理整頓という技術"&gt;整理整頓という技術&#10;&lt;/h2&gt;&lt;p&gt;複数の動画を扱うとき、ファイル名の管理は混沌に陥りがちだ。そこで役立つのが出力指定オプションである。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;yt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dlp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;%(title)s.%(ext)s&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;youtube&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;XXXXXXXXXXX&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;%(title)s&lt;/code&gt;は動画タイトル、&lt;code&gt;%(ext)s&lt;/code&gt;は拡張子を示す。保存先フォルダを指定したければ、パスを追加することもできる。この設定ひとつで、ライブラリ全体が整然と並ぶ。細部へのこだわりが、長期的な快適さを生むのだ。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="フォーマットを選ぶ自由"&gt;フォーマットを選ぶ自由&#10;&lt;/h2&gt;&lt;p&gt;映像のフォーマットや画質を厳密に選びたい場面もある。そのときは、まず利用可能な形式を一覧で確認する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;yt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dlp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;youtube&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;XXXXXXXXXXX&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一覧には画質、コーデック、サイズなどの情報が並ぶ。そこから望むフォーマットIDを指定して実行すればよい。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;yt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dlp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;youtube&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;XXXXXXXXXXX&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コマンドひとつで、容量を抑えたい場合も、高画質を追求したい場合も自在に選べる。この自由度こそが&lt;code&gt;yt-dlp&lt;/code&gt;の真髄である。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="プレイリストを一括で手に入れる"&gt;プレイリストを一括で手に入れる&#10;&lt;/h2&gt;&lt;p&gt;YouTubeのプレイリストURLを指定すれば、連続した動画をまとめてダウンロードできる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;yt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dlp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;youtube&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;XXXXXXXXXXX&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;講義シリーズやミュージックアルバムのような連番構成の動画には特に有効だ。時間を節約し、統一感ある保存が叶う。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="結語コマンドラインに宿る洗練"&gt;結語──コマンドラインに宿る洗練&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;yt-dlp&lt;/code&gt;の魅力は、単なる便利さを超えている。短い命令の中に、精密な制御と柔軟な設計が共存しているからだ。クリック操作では到達できないレベルの自由がここにある。コマンドラインは不器用な人のための道具ではなく、考える者のための筆記具である。&lt;/p&gt;&#10;&lt;p&gt;動画をダウンロードするという単純な行為の背後には、情報をどう扱い、どう保存するかという哲学が潜んでいる。その第一歩として、&lt;code&gt;yt-dlp&lt;/code&gt;を知ることは、デジタル時代のリテラシーの一端を手にすることに等しい。&lt;/p&gt;&#10;</description></item><item><title>Linux/WSLでghqをインストールする方法</title><link>https://ai.hack-le.com/wsl%E3%81%A7ghq%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</link><pubDate>Mon, 27 Oct 2025 18:22:58 +0900</pubDate><guid>https://ai.hack-le.com/wsl%E3%81%A7ghq%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</guid><description>&lt;p&gt;&lt;code&gt;ghq&lt;/code&gt;は、リポジトリを一元的に管理するためのCLIツールである。GitHubやGitLabのリポジトリを一貫したパスで管理し、開発環境を整理するのに非常に有効である。&lt;br&gt;&#10;WSL上ではLinux環境として動作するため、Go製のツールである&lt;code&gt;ghq&lt;/code&gt;を直接ビルド・配置するのが最も適している。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="前提条件"&gt;前提条件&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;項目&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;内容&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;OS&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Windows 10 / 11&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;WSL バージョン&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;2&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Linux ディストリビューション&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Ubuntu 22.04 以降&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Go言語&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1.19 以上（&lt;code&gt;go install&lt;/code&gt;コマンド対応バージョン）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Goが未インストールの場合は、先にGoのインストール手順（前記事参照）を実施する。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="推奨方法go-installで直接インストールする"&gt;推奨方法：&lt;code&gt;go install&lt;/code&gt;で直接インストールする&#10;&lt;/h2&gt;&lt;p&gt;最も標準的で再現性が高い方法は、Go公式ツールチェーンを用いたインストールである。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go install github.com/x-motemen/ghq@latest&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;インストール後、&lt;code&gt;~/go/bin&lt;/code&gt; にバイナリが配置されるため、パスを通す。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;export PATH=$PATH:$(go env GOPATH)/bin&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; ~/.bashrc&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;動作確認を行う。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ghq --version&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで&lt;code&gt;ghq&lt;/code&gt;が利用可能となる。&lt;br&gt;&#10;Goのモジュール管理機能を用いるため、バージョン指定（例：&lt;code&gt;@v1.5.0&lt;/code&gt;）も柔軟に対応できる。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="代替方法apt経由非推奨"&gt;代替方法：APT経由（非推奨）&#10;&lt;/h2&gt;&lt;p&gt;Ubuntuリポジトリにも&lt;code&gt;ghq&lt;/code&gt;パッケージが存在するが、更新が遅くバージョンが古い。&lt;br&gt;&#10;そのため、最新版を利用したい場合には不向きである。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install ghq&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この方法は環境構築を自動化したい場合（例：AnsibleやDockerfileなど）には有効だが、開発者自身の利用には推奨されない。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="ソースからのビルド特殊用途向け"&gt;ソースからのビルド（特殊用途向け）&#10;&lt;/h2&gt;&lt;p&gt;カスタマイズが必要な場合や、&lt;code&gt;ghq&lt;/code&gt;の開発版を試したい場合は、手動でビルドできる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git clone https://github.com/x-motemen/ghq.git&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ghq&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;make install&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;デフォルトでは&lt;code&gt;$GOPATH/bin&lt;/code&gt;にバイナリが生成される。&lt;br&gt;&#10;この方法は、Go開発環境の内部構造を理解している場合にのみ選択すべきである。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;方法&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;特徴&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;推奨度&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;go install github.com/x-motemen/ghq@latest&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;最新版を簡単に導入できる&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;★★★★★&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;apt install ghq&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;システム管理に統合されるが古い&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;★★☆☆☆&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ソースからビルド&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;開発・検証向け&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;★★★☆☆&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="補足環境変数設定の確認"&gt;補足：環境変数設定の確認&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;ghq&lt;/code&gt;は内部で&lt;code&gt;git&lt;/code&gt;コマンドを利用するため、&lt;code&gt;git&lt;/code&gt;がインストールされていることを確認する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git --version&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、デフォルトのリポジトリ保存パスは &lt;code&gt;~/.ghq&lt;/code&gt; である。&lt;br&gt;&#10;変更したい場合は環境変数で指定する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;export GHQ_ROOT=~/dev/src&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; ~/.bashrc&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;p&gt;この構成を採用すれば、WSL上でもLinux環境と同様に&lt;code&gt;ghq&lt;/code&gt;が安定動作し、GitHubリポジトリの管理を効率化できる。&lt;/p&gt;&#10;</description></item><item><title>第3回　Python補完の実践 ― Emacsに頭脳を宿す</title><link>https://ai.hack-le.com/%E7%AC%AC3%E5%9B%9E%E3%80%80python%E8%A3%9C%E5%AE%8C%E3%81%AE%E5%AE%9F%E8%B7%B5-%E2%80%95-emacs%E3%81%AB%E9%A0%AD%E8%84%B3%E3%82%92%E5%AE%BF%E3%81%99/</link><pubDate>Wed, 22 Oct 2025 18:12:52 +0900</pubDate><guid>https://ai.hack-le.com/%E7%AC%AC3%E5%9B%9E%E3%80%80python%E8%A3%9C%E5%AE%8C%E3%81%AE%E5%AE%9F%E8%B7%B5-%E2%80%95-emacs%E3%81%AB%E9%A0%AD%E8%84%B3%E3%82%92%E5%AE%BF%E3%81%99/</guid><description>&lt;p&gt;ここまでで、LSPとは何か、そしてEmacsがそれをどう扱うかを理解した。&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://ai.hack-le.com/%e7%ac%ac2%e5%9b%9e%5cu3000emacs%e3%81%8clsp%e3%82%92%e8%a9%b1%e3%81%99-%e2%80%95-%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e3%81%ae%e4%b8%96%e7%95%8c/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;第2回\u3000EmacsがLSPを話す ― クライアントの世界&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/第2回\u3000emacsがlspを話す-―-クライアントの世界/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://ai.hack-le.com/images/uploads/2025/10/output-22.webp" alt="第2回\u3000EmacsがLSPを話す ― クライアントの世界" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;p&gt;最終回では、実際にPython補完を動かすための構築手順を示す。&lt;br&gt;&#10;目的は単純だ。「なんとなく動いた」ではなく、「なぜそうなるか」を理解したうえで、確信をもって環境を作ることである。&lt;br&gt;&#10;Emacsは設定が複雑なようでいて、理屈が分かれば極めて論理的な道具である。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="python用lspサーバの選択肢"&gt;Python用LSPサーバの選択肢&#10;&lt;/h2&gt;&lt;p&gt;LSPサーバは、言語ごとに独立した解析プロセスである。&lt;br&gt;&#10;Python用には主に次の二つが使われている。&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;サーバ&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;実装&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;特徴&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;python-lsp-server（pylsp）&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Python製&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;標準的で扱いやすく、拡張が豊富。Emacsとの親和性が高い。&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;pyright&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;TypeScript製（Microsoft）&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;高速で型解析が強力。静的型を多用するコードベース向け。&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;どちらもLSP仕様に従うため、クライアント（&lt;code&gt;lsp-mode&lt;/code&gt;/&lt;code&gt;eglot&lt;/code&gt;）から見れば等価である。&lt;br&gt;&#10;決めるべきは、「柔軟なPython的挙動を重視するか」「型安全性と速度を取るか」だ。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="サーバの導入"&gt;サーバの導入&#10;&lt;/h2&gt;&lt;p&gt;仮想環境を使っている場合は、その中にインストールするのが望ましい。&lt;br&gt;&#10;グローバルに導入する場合は以下のようにする。&lt;/p&gt;&#10;&lt;h3 id="pylspの場合"&gt;pylspの場合&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install &amp;#34;python-lsp-server[all]&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで &lt;code&gt;pylsp&lt;/code&gt; コマンドが使えるようになる。&lt;br&gt;&#10;&lt;code&gt;[all]&lt;/code&gt; オプションはflake8やmccabeなどLint系のプラグインもまとめて導入する。&lt;/p&gt;&#10;&lt;h3 id="pyrightの場合"&gt;pyrightの場合&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install -g pyright&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こちらはNode.js環境が必要である。型チェックを多用するプロジェクト向けだ。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="emacs側の準備"&gt;Emacs側の準備&#10;&lt;/h2&gt;&lt;p&gt;ここからは、LSPクライアントとして &lt;code&gt;lsp-mode&lt;/code&gt; を例にとる。&lt;br&gt;&#10;&lt;code&gt;eglot&lt;/code&gt; を使う場合も設定は簡略化されるだけで、概念は同じだ。&lt;/p&gt;&#10;&lt;h3 id="基本設定例use-package使用"&gt;基本設定例（use-package使用）&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-lisp" data-lang="lisp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;lsp-mode&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:hook&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;python-mode&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;lsp-deferred&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:commands&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lsp&lt;/span&gt; &lt;span class="nv"&gt;lsp-deferred&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:config&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;lsp-prefer-flymake&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;; flycheckを使う場合&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;lsp-ui&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:commands&lt;/span&gt; &lt;span class="nv"&gt;lsp-ui-mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;company&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:config&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-company-mode&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでPythonファイルを開いた時に自動でLSPサーバが起動し、&lt;br&gt;&#10;補完・定義ジャンプ・ドキュメント表示などが可能になる。&lt;br&gt;&#10;裏では&lt;code&gt;lsp-mode&lt;/code&gt;が&lt;code&gt;pylsp&lt;/code&gt;プロセスを立ち上げ、JSON-RPCで通信している。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="動作確認"&gt;動作確認&#10;&lt;/h2&gt;&lt;p&gt;Emacsで任意の&lt;code&gt;.py&lt;/code&gt;ファイルを開き、数行書いてみる。&lt;br&gt;&#10;&lt;code&gt;import os&lt;/code&gt; の後に &lt;code&gt;os.&lt;/code&gt; と打てば、補完候補が即座に表示されるはずだ。&lt;br&gt;&#10;もし表示されない場合は、&lt;code&gt;M-x lsp-describe-session&lt;/code&gt; でサーバの状態を確認できる。&lt;br&gt;&#10;通信が確立していれば、そこに &lt;code&gt;pylsp&lt;/code&gt; または &lt;code&gt;pyright&lt;/code&gt; のプロセス情報が出る。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="周辺ツールの統合"&gt;周辺ツールの統合&#10;&lt;/h2&gt;&lt;p&gt;LSPは補完だけではなく、周辺ツールとも密接に連携する。&lt;br&gt;&#10;特にPython環境では以下の3つが鉄板である。&lt;/p&gt;&#10;&lt;h3 id="自動整形blacken"&gt;自動整形：blacken&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(use-package blacken&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; :hook (python-mode . blacken-mode))&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;保存時に &lt;code&gt;black&lt;/code&gt; でコードを整形する。&lt;/p&gt;&#10;&lt;h3 id="構文チェックflycheck"&gt;構文チェック：flycheck&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(use-package flycheck&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; :init (global-flycheck-mode))&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;エラーをリアルタイムで表示。&lt;code&gt;pylsp&lt;/code&gt;にも統合されているが、外付けで使うと制御しやすい。&lt;/p&gt;&#10;&lt;h3 id="仮想環境切替pyvenv"&gt;仮想環境切替：pyvenv&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(use-package pyvenv&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; :config&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; (pyvenv-tracking-mode 1))&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;プロジェクトごとに異なる環境を自動で反映する。&lt;/p&gt;&#10;&lt;p&gt;これらを組み合わせることで、補完だけでなく実行環境全体が整う。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="eglot-を使う場合"&gt;&lt;code&gt;eglot&lt;/code&gt; を使う場合&#10;&lt;/h2&gt;&lt;p&gt;Emacs 29以降であれば、&lt;code&gt;eglot&lt;/code&gt; は標準で使える。&lt;br&gt;&#10;設定は驚くほど少ない。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(use-package eglot&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; :hook (python-mode . eglot-ensure))&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以上で完了だ。&lt;br&gt;&#10;補完はEmacs標準の &lt;code&gt;completion-at-point&lt;/code&gt; に統合され、&lt;code&gt;company&lt;/code&gt; も自然に動作する。&lt;br&gt;&#10;構造的には &lt;code&gt;lsp-mode&lt;/code&gt; と同じ三層だが、設定と依存が極端に少ない。&lt;br&gt;&#10;LSPという機構そのものを理解する目的なら、まずは&lt;code&gt;eglot&lt;/code&gt;で始めるのが良い。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="実際の動作の理解"&gt;実際の動作の理解&#10;&lt;/h2&gt;&lt;p&gt;Python補完が動くとき、背後では次のやり取りが行われている。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Emacs → pylsp: &amp;#34;この位置の補完候補をくれ&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pylsp → Emacs: &amp;#34;print, property, process, ...&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;単純だが、これがすべての基本である。&lt;br&gt;&#10;サーバが変わってもこの会話形式は変わらない。&lt;br&gt;&#10;だからこそ、EmacsでもVSCodeでも同じ補完が得られる。&lt;br&gt;&#10;LSPという共通言語が、エディタの枠を越えた知能を可能にしている。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;Python補完を動かすには、&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;LSPサーバ（&lt;code&gt;pylsp&lt;/code&gt; or &lt;code&gt;pyright&lt;/code&gt;）を導入し、&lt;/li&gt;&#10;&lt;li&gt;Emacsクライアント（&lt;code&gt;lsp-mode&lt;/code&gt; or &lt;code&gt;eglot&lt;/code&gt;）で通信を確立し、&lt;/li&gt;&#10;&lt;li&gt;UI層（&lt;code&gt;company&lt;/code&gt;, &lt;code&gt;flycheck&lt;/code&gt;, &lt;code&gt;blacken&lt;/code&gt;など）で結果を扱う。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;この三層を理解しておけば、どんな構成にも柔軟に対応できる。&lt;br&gt;&#10;Emacsは「設定地獄」と呼ばれがちだが、それは自由の裏返しである。&lt;br&gt;&#10;自分で理屈を掴み、構造を選び、道具を組み立ててこそEmacsである。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="終わりに"&gt;終わりに&#10;&lt;/h2&gt;&lt;p&gt;この三部作を通じて伝えたかったのは、「LSPを理解すれば、Emacsは現代的IDEと同じ地平に立てる」という事実だ。&lt;br&gt;&#10;LSPはEmacsを変えるものではなく、&lt;strong&gt;Emacsの自由さを外の世界へ拡張する手段&lt;/strong&gt;である。&lt;br&gt;&#10;設定例を丸写しにするのではなく、どう動くかを知り、自分の思想に合わせて構築してほしい。&lt;br&gt;&#10;Emacsは道具であり、思想である。&lt;br&gt;&#10;そしてLSPは、その思想を現代に接続するための共通語にすぎない。&lt;/p&gt;&#10;</description></item><item><title>第2回　EmacsがLSPを話す ― クライアントの世界</title><link>https://ai.hack-le.com/%E7%AC%AC2%E5%9B%9E%E3%80%80emacs%E3%81%8Clsp%E3%82%92%E8%A9%B1%E3%81%99-%E2%80%95-%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%E3%81%AE%E4%B8%96%E7%95%8C/</link><pubDate>Wed, 22 Oct 2025 18:07:59 +0900</pubDate><guid>https://ai.hack-le.com/%E7%AC%AC2%E5%9B%9E%E3%80%80emacs%E3%81%8Clsp%E3%82%92%E8%A9%B1%E3%81%99-%E2%80%95-%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%E3%81%AE%E4%B8%96%E7%95%8C/</guid><description>&lt;p&gt;前回、LSP（Language Server Protocol）とは何かを整理した。&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://ai.hack-le.com/%e7%ac%ac1%e5%9b%9e%5cu3000emacs%e3%81%a7python%e8%a3%9c%e5%ae%8c%e3%82%92%e8%80%83%e3%81%88%e3%82%8b%e5%89%8d%e3%81%ab-%e2%80%95-lsp%e3%81%a8%e3%81%af%e4%bd%95%e3%81%8b/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;第1回\u3000EmacsでPython補完を考える前に ― LSPとは何か&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/第1回\u3000emacsでpython補完を考える前に-―-lspとは何か/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://ai.hack-le.com/images/uploads/2025/10/output-21.webp" alt="第1回\u3000EmacsでPython補完を考える前に ― LSPとは何か" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;p&gt;今回は、EmacsがそのLSPをどう扱うかを掘り下げる。&lt;br&gt;&#10;EmacsはLSPを直接理解しているわけではなく、&lt;strong&gt;クライアントとしてLSPサーバと通信する層&lt;/strong&gt;を持っている。&lt;br&gt;&#10;その中核となるのが &lt;code&gt;lsp-mode&lt;/code&gt; と &lt;code&gt;eglot&lt;/code&gt; という二つの実装である。&lt;br&gt;&#10;両者は同じLSPをしゃべるが、&lt;strong&gt;思想と構造が根本的に異なる&lt;/strong&gt;。&lt;br&gt;&#10;この違いを理解することが、自分に合った環境を選ぶ鍵になる。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="emacsにおけるlspクライアントの役割"&gt;EmacsにおけるLSPクライアントの役割&#10;&lt;/h2&gt;&lt;p&gt;LSPクライアントとは、要するに「エディタの代わりにサーバと話す通訳」である。&lt;br&gt;&#10;Emacsが自分で補完や解析を行うわけではない。&lt;br&gt;&#10;代わりに、クライアントがJSON-RPCでLSPサーバに要求を送り、結果を受け取る。&lt;br&gt;&#10;たとえば、ユーザーが関数名の途中まで入力したとき、Emacsはこう動く。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;code&gt;company&lt;/code&gt; などの補完UIが「候補を出せ」と要求&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;lsp-mode&lt;/code&gt;（または&lt;code&gt;eglot&lt;/code&gt;）がサーバに &lt;code&gt;textDocument/completion&lt;/code&gt; を送信&lt;/li&gt;&#10;&lt;li&gt;サーバが解析結果（候補リスト）を返す&lt;/li&gt;&#10;&lt;li&gt;クライアントが結果をUI層へ渡す&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;この通信を隠蔽し、自然な操作感を実現するのがクライアントの仕事である。&lt;br&gt;&#10;つまりLSPクライアントは「通信」と「Emacs統合」の境界に立つ存在である。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="lsp-mode--機能主義と総合化の道"&gt;&lt;code&gt;lsp-mode&lt;/code&gt; ― 機能主義と総合化の道&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;lsp-mode&lt;/code&gt; はEmacsにおける最古参かつ最強のLSPクライアントである。&lt;br&gt;&#10;設計思想は明確だ。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;「Emacsを現代的IDEの水準に引き上げる」&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;&lt;code&gt;lsp-mode&lt;/code&gt; はLSP仕様のほぼ全てのメソッドを実装している。&lt;br&gt;&#10;補完だけでなく、定義ジャンプ、リネーム、コードアクション、ドキュメント表示、フォーマットなどを統合的に扱う。&lt;br&gt;&#10;さらに、&lt;code&gt;lsp-ui&lt;/code&gt;, &lt;code&gt;lsp-treemacs&lt;/code&gt;, &lt;code&gt;lsp-ivy&lt;/code&gt; などの拡張で、VSCode的な体験を再現できる。&lt;br&gt;&#10;一方で、設定項目が膨大で、依存パッケージも多い。&lt;br&gt;&#10;IDE的快適さを求める代わりに、軽量さと単純さを犠牲にしている。&lt;/p&gt;&#10;&lt;p&gt;構造的には、LSPの上にUIや便利関数を積み上げる形だ。&lt;br&gt;&#10;「フル装備の戦車」とでも言うべきクライアントである。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="eglot--簡潔主義とemacs的統合の道"&gt;&lt;code&gt;eglot&lt;/code&gt; ― 簡潔主義とEmacs的統合の道&#10;&lt;/h2&gt;&lt;p&gt;対する &lt;code&gt;eglot&lt;/code&gt; は正反対の思想を持つ。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;「Emacsはすでに優れている。LSPはそれを邪魔せず溶け込むべきだ」&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;&lt;code&gt;eglot&lt;/code&gt; は2018年に登場し、Emacs 29で公式に同梱された。&lt;br&gt;&#10;基本コマンドは &lt;code&gt;M-x eglot&lt;/code&gt; ひとつ。&lt;br&gt;&#10;特別な設定をほとんど要せず、仮想環境やプロジェクトを自動認識してLSPサーバを起動する。&lt;br&gt;&#10;UI拡張はほぼ持たず、既存の &lt;code&gt;xref&lt;/code&gt;（定義ジャンプ）、&lt;code&gt;eldoc&lt;/code&gt;（関数ドキュメント）、&lt;code&gt;flymake&lt;/code&gt;（警告表示）と自然に統合する。&lt;br&gt;&#10;このシンプルさが「Emacsらしさ」を保つ理由である。&lt;/p&gt;&#10;&lt;p&gt;結果、&lt;code&gt;eglot&lt;/code&gt; は軽量で安定しており、コードの可読性も高い。&lt;br&gt;&#10;だが、VSCode的な華やかなUIや細かなチューニングはない。&lt;br&gt;&#10;「Emacsそのものを信頼している」派のための実装である。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="両者の比較と選択の軸"&gt;両者の比較と選択の軸&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;項目&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;code&gt;lsp-mode&lt;/code&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;code&gt;eglot&lt;/code&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;目的&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;IDE的統合&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Emacs標準との自然な融合&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;開発母体&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;独立コミュニティ&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;GNU Emacs本体&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;拡張性&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;高い（UI拡張多数）&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;控えめ&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;設定難度&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;高い&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;低い&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;動作の軽さ&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;中〜重&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;軽&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;更新頻度&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;非常に高い&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;安定重視&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;両者の差は、&lt;strong&gt;便利さを取るか、純粋さを取るか&lt;/strong&gt;に尽きる。&lt;br&gt;&#10;自分のEmacsを“戦車”にしたいなら &lt;code&gt;lsp-mode&lt;/code&gt;、&lt;br&gt;&#10;“機敏な道具”として維持したいなら &lt;code&gt;eglot&lt;/code&gt; を選ぶとよい。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="クライアントとuiの分離--emacs哲学の体現"&gt;クライアントとUIの分離 ― Emacs哲学の体現&#10;&lt;/h2&gt;&lt;p&gt;Emacsでは、LSPクライアントとUIは厳密に分離されている。&lt;br&gt;&#10;理由は単純で、&lt;strong&gt;自由度と再利用性を保つため&lt;/strong&gt;である。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;company-mode&lt;/code&gt;, &lt;code&gt;corfu&lt;/code&gt;, &lt;code&gt;icomplete&lt;/code&gt; など、補完UIの選択肢は無数にある。&lt;br&gt;&#10;LSPクライアントが特定のUIに依存すると、ユーザーの自由を奪う。&lt;br&gt;&#10;そのためクライアントは「候補を返す」までで止まり、&lt;br&gt;&#10;表示は既存の補完システムに任せるよう設計されている。&lt;br&gt;&#10;この設計は、Emacsの原則――「すべては組み合わせ可能（composable）」――の延長線上にある。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;EmacsがLSPを扱う際、中心となるのは &lt;code&gt;lsp-mode&lt;/code&gt; と &lt;code&gt;eglot&lt;/code&gt; という二つのクライアントである。&lt;br&gt;&#10;どちらを選ぶかは「何を求めるか」によって決まる。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;IDE的な利便性を求めるなら &lt;code&gt;lsp-mode&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Emacsの一体感を重視するなら &lt;code&gt;eglot&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;重要なのは、どちらを選んでも&lt;strong&gt;LSPという共通言語を通じて同じサーバを使える&lt;/strong&gt;という事実だ。&lt;br&gt;&#10;道具は違えど、話している言葉は同じ。&lt;br&gt;&#10;次回は、そのサーバ側――すなわち &lt;strong&gt;PythonのLSPサーバ実装（&lt;code&gt;pylsp&lt;/code&gt;と&lt;code&gt;pyright&lt;/code&gt;）&lt;/strong&gt; の実践編に進む。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;p&gt;次の第3回では、実際にEmacsでPython補完を動かし、&lt;code&gt;lsp-mode&lt;/code&gt; または &lt;code&gt;eglot&lt;/code&gt; と組み合わせて設定する過程を解説する。&lt;/p&gt;&#10;</description></item><item><title>第1回　EmacsでPython補完を考える前に ― LSPとは何か</title><link>https://ai.hack-le.com/%E7%AC%AC1%E5%9B%9E%E3%80%80emacs%E3%81%A7python%E8%A3%9C%E5%AE%8C%E3%82%92%E8%80%83%E3%81%88%E3%82%8B%E5%89%8D%E3%81%AB-%E2%80%95-lsp%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%8B/</link><pubDate>Wed, 22 Oct 2025 17:57:28 +0900</pubDate><guid>https://ai.hack-le.com/%E7%AC%AC1%E5%9B%9E%E3%80%80emacs%E3%81%A7python%E8%A3%9C%E5%AE%8C%E3%82%92%E8%80%83%E3%81%88%E3%82%8B%E5%89%8D%E3%81%AB-%E2%80%95-lsp%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%8B/</guid><description>&lt;p&gt;EmacsでPythonを書くとき、最初にぶつかる壁が「補完」である。&lt;br&gt;&#10;関数名や変数名を自動で提示してくれる機能だが、Emacsにおける補完の仕組みは複雑である。単に候補を出すだけではなく、背後に&lt;strong&gt;構文解析や通信プロトコル&lt;/strong&gt;が存在する。&lt;br&gt;&#10;本稿では、設定やプラグインの話をする前に、その背後にある「LSP（Language Server Protocol）」という概念を理解することを目的とする。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="lsp以前--言語ごとに分裂していた時代"&gt;LSP以前 ― 言語ごとに分裂していた時代&#10;&lt;/h2&gt;&lt;p&gt;かつて、Emacsの補完は&lt;strong&gt;言語ごとの独自実装&lt;/strong&gt;に依存していた。&lt;br&gt;&#10;Pythonなら&lt;code&gt;jedi.el&lt;/code&gt;、C++なら&lt;code&gt;rtags&lt;/code&gt;、Javaなら&lt;code&gt;eclim&lt;/code&gt;といった具合である。&lt;br&gt;&#10;各パッケージが独自に解析を行い、独自のプロトコルで補完情報を渡していた。&lt;br&gt;&#10;結果として、言語が増えるたびに新しいElisp実装が必要になり、保守は煩雑を極めた。&lt;br&gt;&#10;「C言語での定義ジャンプと、Pythonでの補完が全く別物」という状況は当たり前であった。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="lspの登場--共通言語の誕生"&gt;LSPの登場 ― 共通言語の誕生&#10;&lt;/h2&gt;&lt;p&gt;その混乱を整理したのが&lt;strong&gt;LSP（Language Server Protocol）である。2016年頃、Visual Studio Codeの開発チームが「どの言語でも同じ方法で補完や解析を行える共通プロトコル」を設計した。LSPはエディタと解析サーバのあいだの通信仕様&lt;/strong&gt;であり、JSON-RPCを使ってやりとりを行う。&lt;/p&gt;&#10;&lt;p&gt;LSPを導入したエディタは、もう言語ごとの補完ロジックを持つ必要がない。&lt;br&gt;&#10;エディタは「クライアント」として統一プロトコルを喋り、解析は「サーバ」が行う。&lt;br&gt;&#10;たとえばEmacs・Vim・VSCodeがすべて&lt;strong&gt;同じPython解析サーバ（例：pylsp）&lt;/strong&gt; を使える。&lt;br&gt;&#10;これにより、「解析エンジンは共通、UIは各エディタ流儀」という分業が成立した。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="エディタとサーバの関係"&gt;エディタとサーバの関係&#10;&lt;/h2&gt;&lt;p&gt;LSPでは、以下のような通信が行われる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Emacs → LSPサーバ：&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; textDocument/completion を要求&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;LSPサーバ → Emacs：&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; [&amp;#34;print&amp;#34;, &amp;#34;printf&amp;#34;, &amp;#34;println&amp;#34;] を返す&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これが補完の実体である。&lt;br&gt;&#10;エディタはただ「この位置の候補をくれ」と依頼し、サーバは解析結果を返す。&lt;br&gt;&#10;LSPはその&lt;strong&gt;共通の会話の文法&lt;/strong&gt;を定めたものであり、特定エディタには依存しない。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="lspの三層構造"&gt;LSPの三層構造&#10;&lt;/h2&gt;&lt;p&gt;LSPを理解するうえで重要なのが三層構造である。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;UI層&lt;/strong&gt; … 候補を画面に出す。&lt;code&gt;company-mode&lt;/code&gt;や&lt;code&gt;corfu&lt;/code&gt;が該当する。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;クライアント層&lt;/strong&gt; … サーバと通信し、データを受け取る。&lt;code&gt;lsp-mode&lt;/code&gt;や&lt;code&gt;eglot&lt;/code&gt;がここ。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;サーバ層&lt;/strong&gt; … 実際に言語を解析する。&lt;code&gt;pylsp&lt;/code&gt;や&lt;code&gt;pyright&lt;/code&gt;など。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;Emacsではこれらが独立しており、ユーザーは好きな組み合わせを選べる。&lt;br&gt;&#10;UIを変えてもサーバは同じ、サーバを変えてもUIはそのまま――この柔軟さこそがEmacs的である。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="オープンな標準としてのlsp"&gt;オープンな標準としてのLSP&#10;&lt;/h2&gt;&lt;p&gt;LSPはMicrosoft発祥ではあるが、現在は&lt;strong&gt;Eclipse FoundationのLSP Working Group&lt;/strong&gt;によりオープンに策定されている。&lt;br&gt;&#10;仕様はGitHub上で公開され、誰でも提案・修正が可能である。&lt;br&gt;&#10;確かに企業の影響は残るが、プロトコル自体は&lt;strong&gt;フリーであり、ロックインされない&lt;/strong&gt;。&lt;br&gt;&#10;Emacsにおいても、&lt;code&gt;lsp-mode&lt;/code&gt;や&lt;code&gt;eglot&lt;/code&gt;がこのプロトコルを実装し、純粋に「通信仕様」として扱っている。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;LSPとは、エディタと解析サーバをつなぐ共通語であり、&lt;br&gt;&#10;従来の「言語ごと・エディタごと」の個別実装を終わらせるものである。&lt;br&gt;&#10;これを理解すれば、EmacsがVSCodeと同じ補完精度を実現できる理由が見えてくるだろう。&lt;br&gt;&#10;次回は、このLSPをEmacsがどう扱うのか、つまり&lt;strong&gt;クライアント層の構造と思想&lt;/strong&gt;を掘り下げていく。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;p&gt;この稿は、次の第2回「EmacsがLSPを話す ― クライアントの世界」へ続く。&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://ai.hack-le.com/%e7%ac%ac2%e5%9b%9e%5cu3000emacs%e3%81%8clsp%e3%82%92%e8%a9%b1%e3%81%99-%e2%80%95-%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e3%81%ae%e4%b8%96%e7%95%8c/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;第2回\u3000EmacsがLSPを話す ― クライアントの世界&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/第2回\u3000emacsがlspを話す-―-クライアントの世界/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://ai.hack-le.com/images/uploads/2025/10/output-22.webp" alt="第2回\u3000EmacsがLSPを話す ― クライアントの世界" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;</description></item><item><title>macOS launchctl の bootstrap と bootout コマンドの使い方</title><link>https://ai.hack-le.com/macos-launchctl-%E3%81%AE-bootstrap-%E3%81%A8-bootout-%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9/</link><pubDate>Wed, 08 Oct 2025 17:21:45 +0900</pubDate><guid>https://ai.hack-le.com/macos-launchctl-%E3%81%AE-bootstrap-%E3%81%A8-bootout-%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9/</guid><description>&lt;p&gt;macOS では、バックグラウンドで動作するサービス（デーモンやエージェント）を管理するために &lt;code&gt;launchd&lt;/code&gt; という仕組みが用いられており、これを制御するコマンドが &lt;code&gt;launchctl&lt;/code&gt; である。従来は &lt;code&gt;load&lt;/code&gt; と &lt;code&gt;unload&lt;/code&gt; というサブコマンドが使われていたが、macOS 10.11 El Capitan 以降、これらは「レガシーサブコマンド」として扱われ、代わりに &lt;code&gt;bootstrap&lt;/code&gt; と &lt;code&gt;bootout&lt;/code&gt; が推奨されるようになった。ただし実際には、2025年現在も多くの記事やスクリプトで従来の &lt;code&gt;load&lt;/code&gt;/&lt;code&gt;unload&lt;/code&gt; が使われ続けているのが現状である。&lt;/p&gt;&#10;&lt;p&gt;本記事では、公式に推奨されている &lt;code&gt;bootstrap&lt;/code&gt; と &lt;code&gt;bootout&lt;/code&gt; の使い方について解説する。なお、この記事で扱う内容は macOS 10.11 以降を前提としている。&lt;/p&gt;&#10;&lt;h2 id="bootstrap-と-bootout-の基本"&gt;bootstrap と bootout の基本&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;bootstrap&lt;/code&gt; と &lt;code&gt;bootout&lt;/code&gt; は、それぞれ従来の &lt;code&gt;load&lt;/code&gt; と &lt;code&gt;unload&lt;/code&gt; に相当するコマンドである。最大の違いは、&lt;strong&gt;ドメインを明示的に指定する必要がある&lt;/strong&gt;という点だ。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;bootstrap&lt;/code&gt;: サービスをドメインに登録して起動する（&lt;code&gt;load&lt;/code&gt; の代替）&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;bootout&lt;/code&gt;: サービスを停止してドメインから削除する（&lt;code&gt;unload&lt;/code&gt; の代替）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;従来の方式では、plist ファイルのパスから暗黙的にドメインが判別されていたが、新しい方式では明示的に指定することで、より正確な制御が可能になるという設計思想である。&lt;/p&gt;&#10;&lt;h2 id="ドメインの種類と意味"&gt;ドメインの種類と意味&#10;&lt;/h2&gt;&lt;p&gt;launchd におけるドメインとは、サービスがどのレベル・どのユーザーのために動作するかを表す概念である。主なドメインは以下の3種類だ。&lt;/p&gt;&#10;&lt;h3 id="system-ドメイン"&gt;system ドメイン&#10;&lt;/h3&gt;&lt;p&gt;システム全体で動作するデーモンのためのドメインである。root 権限で実行され、すべてのユーザーに影響する。通常、&lt;code&gt;/Library/LaunchDaemons/&lt;/code&gt; に配置された plist ファイルがこのドメインで動作する。&lt;/p&gt;&#10;&lt;h3 id="guiuid-ドメイン"&gt;gui/UID ドメイン&#10;&lt;/h3&gt;&lt;p&gt;特定のユーザーがグラフィカルログイン（GUI セッション）している間だけ動作するエージェントのためのドメインである。UID はユーザー ID を表す数値で、macOS では最初に作成されたユーザーは通常 501 となる。自分の UID は &lt;code&gt;id -u&lt;/code&gt; コマンドで確認できる。&lt;code&gt;~/Library/LaunchAgents/&lt;/code&gt; や &lt;code&gt;/Library/LaunchAgents/&lt;/code&gt; に配置されたエージェントは、基本的にこのドメインで動作する。&lt;/p&gt;&#10;&lt;h3 id="useruid-ドメイン"&gt;user/UID ドメイン&#10;&lt;/h3&gt;&lt;p&gt;特定のユーザー権限で動作するが、ログインの有無に関わらず常駐するバックグラウンドサービスのためのドメインである。GUI は使用できないが、PC 起動中は常に動き続ける。このドメインは macOS 10.11 以降で追加された比較的新しい概念である。&lt;/p&gt;&#10;&lt;h2 id="基本的な使い方"&gt;基本的な使い方&#10;&lt;/h2&gt;&lt;h3 id="システムデーモンの登録と削除"&gt;システムデーモンの登録と削除&#10;&lt;/h3&gt;&lt;p&gt;システム全体で動作するデーモンを扱う場合、&lt;code&gt;system&lt;/code&gt; ドメインを指定する。root 権限が必要なため、&lt;code&gt;sudo&lt;/code&gt; を付けて実行する必要がある。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 登録（起動）&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo launchctl bootstrap system /Library/LaunchDaemons/com.example.daemon.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 削除（停止）&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo launchctl bootout system /Library/LaunchDaemons/com.example.daemon.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ユーザーエージェントの登録と削除"&gt;ユーザーエージェントの登録と削除&#10;&lt;/h3&gt;&lt;p&gt;ログイン中のユーザーのために動作するエージェントを扱う場合、&lt;code&gt;gui/UID&lt;/code&gt; ドメインを指定する。まず自分の UID を確認してから、その値を使ってコマンドを実行する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# UID を確認&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;id -u&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 例: 501 と表示される&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 登録（起動）&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;launchctl bootstrap gui/501 ~/Library/LaunchAgents/com.example.agent.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 削除（停止）&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;launchctl bootout gui/501 ~/Library/LaunchAgents/com.example.agent.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;スクリプト内で動的に UID を取得する場合は、以下のように記述できる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 現在ログイン中のユーザーの UID を取得&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;USER_ID=$(id -u)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 登録&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;launchctl bootstrap gui/$USER_ID ~/Library/LaunchAgents/com.example.agent.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 削除&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;launchctl bootout gui/$USER_ID ~/Library/LaunchAgents/com.example.agent.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="サービスの状態確認"&gt;サービスの状態確認&#10;&lt;/h3&gt;&lt;p&gt;登録されているサービスの一覧を確認するには、&lt;code&gt;launchctl list&lt;/code&gt; コマンドを使う。特定のサービスを grep で絞り込むことも可能だ。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# すべてのサービスを表示&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;launchctl list&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 特定のサービスを検索&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;launchctl list | grep com.example&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;より詳細な情報を得るには、&lt;code&gt;launchctl print&lt;/code&gt; コマンドを使う。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# システムドメインの情報を表示&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo launchctl print system&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 特定のユーザードメインの情報を表示&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;launchctl print gui/501&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 特定のサービスの詳細を表示&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;launchctl print gui/501/com.example.agent&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ただし、&lt;code&gt;print&lt;/code&gt; コマンドの出力形式は公式には構造化されておらず、バージョン間で変更される可能性があるため、スクリプトでのパース処理には依存しないことが推奨されている。&lt;/p&gt;&#10;&lt;h2 id="実行中のサービスの再起動"&gt;実行中のサービスの再起動&#10;&lt;/h2&gt;&lt;p&gt;既に動作しているサービスを再起動したい場合、&lt;code&gt;bootout&lt;/code&gt; してから &lt;code&gt;bootstrap&lt;/code&gt; し直す方法もあるが、より簡単な方法として &lt;code&gt;kickstart&lt;/code&gt; コマンドが用意されている。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# サービスを再起動（-k オプションで既存のインスタンスを終了してから起動）&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;launchctl kickstart -k gui/501/com.example.agent&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;-k&lt;/code&gt; オプションを付けると、既に動作中のインスタンスを終了してから新しいインスタンスを起動する。オプションなしで実行すると、既に動作中の場合はエラーとなる。&lt;/p&gt;&#10;&lt;h2 id="enable-と-disable-の使い分け"&gt;enable と disable の使い分け&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;bootstrap&lt;/code&gt;/&lt;code&gt;bootout&lt;/code&gt; とは別に、&lt;code&gt;enable&lt;/code&gt; と &lt;code&gt;disable&lt;/code&gt; というサブコマンドも存在する。これらはサービスを有効化・無効化するためのもので、次回のブート時やログイン時にサービスを自動起動するかどうかを制御する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# サービスを無効化（次回から自動起動しない）&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo launchctl disable system/com.example.daemon&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# サービスを有効化（次回から自動起動する）&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo launchctl enable system/com.example.daemon&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意点として、&lt;code&gt;disable&lt;/code&gt; でサービスを無効化した後は、単に &lt;code&gt;bootstrap&lt;/code&gt; しようとしてもエラーになる。再度有効にするには、まず &lt;code&gt;enable&lt;/code&gt; を実行してから &lt;code&gt;bootstrap&lt;/code&gt; する必要がある。&lt;/p&gt;&#10;&lt;h2 id="従来の-loadunload-との対応関係"&gt;従来の load/unload との対応関係&#10;&lt;/h2&gt;&lt;p&gt;従来の方式と新しい方式の対応関係をまとめると、以下のようになる。&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;従来の方式&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;新しい方式&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;launchctl load /Library/LaunchDaemons/service.plist&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;sudo launchctl bootstrap system /Library/LaunchDaemons/service.plist&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;launchctl unload /Library/LaunchDaemons/service.plist&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;sudo launchctl bootout system /Library/LaunchDaemons/service.plist&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;launchctl load ~/Library/LaunchAgents/agent.plist&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/agent.plist&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;launchctl unload ~/Library/LaunchAgents/agent.plist&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/agent.plist&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;従来の方式では plist ファイルのパスから自動的にドメインが判別されていたが、新しい方式ではドメインを明示的に指定する必要がある。この変更により、より正確な制御が可能になったとされているが、実際には記述量が増え、コマンドも覚えにくくなったという側面もある。&lt;/p&gt;&#10;&lt;h2 id="よくある問題とトラブルシューティング"&gt;よくある問題とトラブルシューティング&#10;&lt;/h2&gt;&lt;h3 id="permission-denied-エラー"&gt;Permission denied エラー&#10;&lt;/h3&gt;&lt;p&gt;システムドメインのサービスを操作する際に &lt;code&gt;sudo&lt;/code&gt; を付け忘れると、権限エラーが発生する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# エラー例&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;launchctl bootstrap system /Library/LaunchDaemons/service.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# → Permission denied&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 正しい実行方法&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo launchctl bootstrap system /Library/LaunchDaemons/service.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="operation-now-in-progress-エラー"&gt;Operation now in progress エラー&#10;&lt;/h3&gt;&lt;p&gt;サービスが既に登録されている状態で再度 &lt;code&gt;bootstrap&lt;/code&gt; を実行すると、このエラーが発生する。この場合は、まず &lt;code&gt;bootout&lt;/code&gt; で削除してから再度 &lt;code&gt;bootstrap&lt;/code&gt; する必要がある。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 一度削除してから再登録&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo launchctl bootout system /Library/LaunchDaemons/service.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo launchctl bootstrap system /Library/LaunchDaemons/service.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あるいは、前述の &lt;code&gt;kickstart -k&lt;/code&gt; コマンドを使うことで、より簡潔に再起動できる。&lt;/p&gt;&#10;&lt;h3 id="bootstrap-failed-5-inputoutput-error"&gt;Bootstrap failed: 5: Input/output error&#10;&lt;/h3&gt;&lt;p&gt;サービスを &lt;code&gt;disable&lt;/code&gt; した後に &lt;code&gt;bootstrap&lt;/code&gt; しようとすると、このエラーが発生することがある。この場合は、まず &lt;code&gt;enable&lt;/code&gt; で有効化してから &lt;code&gt;bootstrap&lt;/code&gt; する必要がある。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 正しい手順&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo launchctl enable system/com.example.daemon&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo launchctl bootstrap system /Library/LaunchDaemons/com.example.daemon.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="sip-によるエラー"&gt;SIP によるエラー&#10;&lt;/h3&gt;&lt;p&gt;System Integrity Protection（SIP）が有効な場合、システムが管理する一部の plist ファイルは変更できない。このような場合、以下のようなエラーメッセージが表示される。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Operation not permitted while System Integrity Protection is engaged&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この場合、基本的には操作を諦めるか、SIP を無効化する必要がある（ただし SIP の無効化はセキュリティリスクを伴うため推奨されない）。&lt;/p&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;bootstrap&lt;/code&gt; と &lt;code&gt;bootout&lt;/code&gt; は、macOS 10.11 以降で推奨されている launchd サービスの管理コマンドである。従来の &lt;code&gt;load&lt;/code&gt;/&lt;code&gt;unload&lt;/code&gt; と比べて、ドメインを明示的に指定する必要があるため、より正確な制御が可能になった反面、コマンドが冗長になり覚えにくくなったという側面もある。&lt;/p&gt;&#10;&lt;p&gt;実際には、2025年現在も多くの記事やスクリプトで従来の &lt;code&gt;load&lt;/code&gt;/&lt;code&gt;unload&lt;/code&gt; が使われ続けており、これらのコマンドも依然として動作する。ただし、公式には &lt;code&gt;bootstrap&lt;/code&gt;/&lt;code&gt;bootout&lt;/code&gt; の使用が推奨されているため、新しく書くスクリプトではこちらを使うのが望ましいとされている。&lt;/p&gt;&#10;&lt;p&gt;システムの根幹に関わる launchd の操作は慎重に行う必要がある。特に &lt;code&gt;/Library/LaunchDaemons/&lt;/code&gt; や &lt;code&gt;/System/Library/&lt;/code&gt; 以下のファイルを扱う際は、誤った操作がシステム全体に影響を及ぼす可能性があるため、十分に注意して作業を進めることが重要である。&lt;/p&gt;&#10;&lt;h2 id="出典"&gt;出典&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;Stack Overflow: &lt;a class="link" href="https://stackoverflow.com/questions/57412590/launchd-confusion-on-the-sematics-of-bootstrap-bootout-for-controlling-services" target="_blank" rel="noopener"&#10; &gt;launchd: Confusion on the sematics of bootstrap/bootout for controlling services on macOS&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;Ask Different: &lt;a class="link" href="https://apple.stackexchange.com/questions/366281/launchd-confusion-on-semantics-of-bootstrap-and-bootout-etc-after-reading-manu" target="_blank" rel="noopener"&#10; &gt;launchd: Confusion on semantics of bootstrap and bootout etc. after reading manual pages&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;Alan Siu&amp;rsquo;s Blog: &lt;a class="link" href="https://www.alansiu.net/2023/11/15/launchctl-new-subcommand-basics-for-macos/" target="_blank" rel="noopener"&#10; &gt;launchctl &amp;ldquo;new&amp;rdquo; subcommand basics for macOS&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;SS64.com: &lt;a class="link" href="https://ss64.com/mac/launchctl.html" target="_blank" rel="noopener"&#10; &gt;launchctl Man Page - macOS&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;The Terminal Blogger: &lt;a class="link" href="https://joelsenders.wordpress.com/2019/03/14/dear-launchctl-were-all-using-you-wrong/" target="_blank" rel="noopener"&#10; &gt;Dear Launchctl, We&amp;rsquo;re All Using You Wrong&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;Babo D&amp;rsquo;s Corner: &lt;a class="link" href="https://babodee.wordpress.com/2016/04/09/launchctl-2-0-syntax/" target="_blank" rel="noopener"&#10; &gt;Launchctl 2.0 Syntax&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>ghqで高速リポジトリ移動を実現する最小設定</title><link>https://ai.hack-le.com/ghq%E3%81%A7%E9%AB%98%E9%80%9F%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E7%A7%BB%E5%8B%95%E3%82%92%E5%AE%9F%E7%8F%BE%E3%81%99%E3%82%8B%E6%9C%80%E5%B0%8F%E8%A8%AD%E5%AE%9A/</link><pubDate>Tue, 16 Sep 2025 03:03:42 +0900</pubDate><guid>https://ai.hack-le.com/ghq%E3%81%A7%E9%AB%98%E9%80%9F%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E7%A7%BB%E5%8B%95%E3%82%92%E5%AE%9F%E7%8F%BE%E3%81%99%E3%82%8B%E6%9C%80%E5%B0%8F%E8%A8%AD%E5%AE%9A/</guid><description>&lt;p&gt;ghqを使ってGitリポジトリを管理している際、複数のリポジトリ間を素早く移動したい場面は日常的に発生する。複雑な設定や多機能なツールの組み合わせではなく、最小限の設定で最大の効果を得る方法を紹介する。&lt;/p&gt;&#10;&lt;h2 id="前提環境"&gt;前提環境&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;ghqがインストールされていること&lt;/li&gt;&#10;&lt;li&gt;fzfがインストールされていること&lt;/li&gt;&#10;&lt;li&gt;Bash または Zsh を使用していること&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;fzfのインストールは以下のコマンドで実行できる：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# macOS (Homebrew)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;brew install fzf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Ubuntu/Debian&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install fzf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# CentOS/RHEL&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum install fzf&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="最小構成での設定方法"&gt;最小構成での設定方法&#10;&lt;/h2&gt;&lt;p&gt;シェルの設定ファイル（&lt;code&gt;.bashrc&lt;/code&gt; または &lt;code&gt;.zshrc&lt;/code&gt;）に以下の1行を追加するだけで、高速なリポジトリ移動が可能になる：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alias g=&amp;#39;cd $(ghq root)/$(ghq list | fzf)&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この設定により、&lt;code&gt;g&lt;/code&gt; コマンドを実行するとfzfの絞り込み画面が表示され、リポジトリ名を入力して絞り込み、Enterキーで該当するリポジトリのディレクトリに移動できる。&lt;/p&gt;&#10;&lt;p&gt;設定後は以下のコマンドで設定を反映させる：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;source ~/.zshrc # Zshの場合&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;source ~/.bashrc # Bashの場合&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="実際の使用例"&gt;実際の使用例&#10;&lt;/h2&gt;&lt;p&gt;例えば、以下のようなリポジトリ構成があるとする：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;~/ghq/github.com/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── user/my-blog&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── user/api-server&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── user/frontend-app&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── company/internal-tool&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;g&lt;/code&gt; コマンドを実行すると、fzfの絞り込み画面が表示される。ここで「blog」と入力すると &lt;code&gt;user/my-blog&lt;/code&gt; が絞り込まれ、Enterキーを押すことで即座に該当ディレクトリに移動する。部分一致での検索が可能なため、「front」と入力すれば &lt;code&gt;user/frontend-app&lt;/code&gt; にマッチする。&lt;/p&gt;&#10;&lt;p&gt;このような直感的な操作により、従来の &lt;code&gt;cd&lt;/code&gt; コマンドで長いパスを入力する必要がなくなり、開発効率が大幅に向上する。&lt;/p&gt;&#10;&lt;h2 id="他の選択肢との比較"&gt;他の選択肢との比較&#10;&lt;/h2&gt;&lt;p&gt;リポジトリ移動を効率化する方法として、pecoを使用する選択肢もある。pecoは日本で人気のあるツールで、基本的な絞り込み機能を提供する。しかし、現在ではfzfの方が機能的に優れており、より活発に開発されている状況である。&lt;/p&gt;&#10;&lt;p&gt;fzfとpecoの主な違いは、fzfがプレビュー機能や複数選択機能を標準で備えている点にある。また、GitHubでのスター数を見ると、fzfが60,000以上のスターを獲得している一方で、pecoは7,000程度となっており、コミュニティの規模と活発度に大きな差がある。&lt;/p&gt;&#10;&lt;p&gt;将来的な拡張性を考慮した場合、fzfを選択しておくことで、プレビュー機能やその他の高度な機能を後から追加できる余地が残される。&lt;/p&gt;&#10;</description></item><item><title>macOSでtacコマンドを使えるようにする設定方法</title><link>https://ai.hack-le.com/macos%E3%81%A7tac%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92%E4%BD%BF%E3%81%88%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95/</link><pubDate>Tue, 16 Sep 2025 02:23:36 +0900</pubDate><guid>https://ai.hack-le.com/macos%E3%81%A7tac%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92%E4%BD%BF%E3%81%88%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95/</guid><description>&lt;p&gt;pecoなどのCLIツールを使用する際に、Linuxでは標準的な&lt;code&gt;tac&lt;/code&gt;コマンドがmacOSでは利用できずエラーが発生することがある。この記事では、macOSで&lt;code&gt;tac&lt;/code&gt;コマンドを使えるようにするための設定手順を記録する。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;検証環境&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;macOS&lt;/li&gt;&#10;&lt;li&gt;Homebrew導入済み&lt;/li&gt;&#10;&lt;li&gt;bash または zsh&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="tacコマンドとは"&gt;tacコマンドとは&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;tac&lt;/code&gt;コマンドは、ファイルの内容を行単位で逆順に出力するLinuxの標準コマンドである。&lt;code&gt;cat&lt;/code&gt;コマンドの逆の動作を行うため、&amp;ldquo;tac&amp;rdquo;（catの逆綴り）という名前が付けられている。主にログファイルの最新エントリから順に表示したい場合や、履歴検索ツールでの逆順処理に使用される。&lt;/p&gt;&#10;&lt;h2 id="macosでのtacコマンド不在問題"&gt;macOSでのtacコマンド不在問題&#10;&lt;/h2&gt;&lt;p&gt;macOSでpecoなどのツールを使用する際に、以下のようなエラーが発生する場合がある：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-bash: tac: command not found&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これは、macOSのBSD系ユーティリティにはGNU系の&lt;code&gt;tac&lt;/code&gt;コマンドが含まれていないことが原因である。多くのLinux環境で当然のように使用されているコマンドであるため、LinuxからmacOSに移行した際によく遭遇する問題となっている。&lt;/p&gt;&#10;&lt;h2 id="coreutilsパッケージによる解決"&gt;coreutilsパッケージによる解決&#10;&lt;/h2&gt;&lt;p&gt;最も確実で標準的な解決方法は、GNU coreutilsパッケージをHomebrewでインストールすることである。GNU coreutilsは、Linux環境で使用されている基本的なコマンド群をmacOSでも利用できるようにするパッケージである。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;brew install coreutils&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このインストールにより、GNU版の各種コマンドが&lt;code&gt;g&lt;/code&gt;プレフィックス付きで利用可能になる。&lt;code&gt;tac&lt;/code&gt;コマンドの場合は&lt;code&gt;gtac&lt;/code&gt;として使用できるようになる。&lt;/p&gt;&#10;&lt;p&gt;インストール後の動作確認：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;echo -e &amp;#34;first\nsecond\nthird&amp;#34; | gtac&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 出力：&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# third&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# second&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# first&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="エイリアスによる透過的な利用"&gt;エイリアスによる透過的な利用&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;gtac&lt;/code&gt;コマンドが使用できるようになったが、既存のスクリプトや設定で&lt;code&gt;tac&lt;/code&gt;として呼び出される場合に対応するため、エイリアスを設定する必要がある。使用しているシェルの設定ファイルにエイリアスを追加することで、&lt;code&gt;tac&lt;/code&gt;コマンドを&lt;code&gt;gtac&lt;/code&gt;に自動的に変換できる。&lt;/p&gt;&#10;&lt;p&gt;bashを使用している場合は&lt;code&gt;~/.bashrc&lt;/code&gt;または&lt;code&gt;~/.bash_profile&lt;/code&gt;に、zshを使用している場合は&lt;code&gt;~/.zshrc&lt;/code&gt;に以下の設定を追加する：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alias tac=&amp;#39;gtac&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;設定を反映させるため、設定ファイルを再読み込みするか、新しいターミナルセッションを開始する：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# bashの場合&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;source ~/.bashrc&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# zshの場合&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;source ~/.zshrc&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="設定の確認"&gt;設定の確認&#10;&lt;/h2&gt;&lt;p&gt;エイリアス設定後、&lt;code&gt;tac&lt;/code&gt;コマンドが正常に動作することを確認する：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# tacコマンドのテスト&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;echo -e &amp;#34;line1\nline2\nline3&amp;#34; | tac&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 期待される出力：&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# line3&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# line2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# line1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、エイリアスが正しく設定されているかは&lt;code&gt;alias&lt;/code&gt;コマンドで確認できる：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alias | grep tac&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 出力: alias tac=&amp;#39;gtac&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="pecoでの履歴検索への適用"&gt;pecoでの履歴検索への適用&#10;&lt;/h2&gt;&lt;p&gt;この設定により、pecoを使用した履歴検索で&lt;code&gt;tac&lt;/code&gt;コマンドが正常に動作するようになる。一般的なpeco設定では、コマンド履歴を逆順で表示するために&lt;code&gt;tac&lt;/code&gt;が使用されており、以下のような設定が機能するようになる：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 例：pecoを使った履歴検索の設定&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;function peco-select-history() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; local tac&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; if which tac &amp;gt; /dev/null; then&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; tac=&amp;#34;tac&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; elif which tail &amp;gt; /dev/null; then&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; tac=&amp;#34;tail -r&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; fi&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; BUFFER=$(history -n 1 | eval $tac | peco --query &amp;#34;$LBUFFER&amp;#34;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; CURSOR=$#BUFFER&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; zle clear-screen&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;macOSでのtacコマンド不在問題は、GNU coreutilsパッケージのインストールとエイリアス設定により解決できる。この設定により、Linux環境で作成されたスクリプトやツール設定をmacOSでもそのまま利用できるようになる。特にpecoやその他のCLIツールを使用する開発環境において、この設定は必須といえる。同様の手法は、GNU系の他のコマンド（&lt;code&gt;gls&lt;/code&gt;、&lt;code&gt;ggrep&lt;/code&gt;など）にも適用でき、Linux環境との互換性を高めることができる。&lt;/p&gt;&#10;</description></item><item><title>macOSでBash起動時のロケール警告を解決する方法</title><link>https://ai.hack-le.com/macos%E3%81%A7bash%E8%B5%B7%E5%8B%95%E6%99%82%E3%81%AE%E3%83%AD%E3%82%B1%E3%83%BC%E3%83%AB%E8%AD%A6%E5%91%8A%E3%82%92%E8%A7%A3%E6%B1%BA%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</link><pubDate>Tue, 16 Sep 2025 01:54:34 +0900</pubDate><guid>https://ai.hack-le.com/macos%E3%81%A7bash%E8%B5%B7%E5%8B%95%E6%99%82%E3%81%AE%E3%83%AD%E3%82%B1%E3%83%BC%E3%83%AB%E8%AD%A6%E5%91%8A%E3%82%92%E8%A7%A3%E6%B1%BA%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</guid><description>&lt;p&gt;macOSでシェルをfishからbashに変更した際、ターミナル起動時に以下のような警告が表示されることがある。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-bash: 警告: setlocale: LC_COLLATE: cannot change locale (): No such file or directory&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この警告は機能上の問題を引き起こすわけではないが、毎回表示されるため作業の邪魔になる。本記事では、この警告を解消する対症療法的な解決方法を記録する。&lt;/p&gt;&#10;&lt;h2 id="環境"&gt;環境&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;macOS（Homebrewでbashをインストール済み）&lt;/li&gt;&#10;&lt;li&gt;シェルをfishからbashに変更後&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;/opt/homebrew/bin/bash&lt;/code&gt;を使用&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="問題の原因分析"&gt;問題の原因分析&#10;&lt;/h2&gt;&lt;h3 id="現在のロケール設定の確認"&gt;現在のロケール設定の確認&#10;&lt;/h3&gt;&lt;p&gt;まず、現在のロケール設定を確認する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;locale&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;問題がある場合、以下のような出力になることが多い。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;LANG=&amp;#34;&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;LC_COLLATE=&amp;#34;C&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;LC_CTYPE=&amp;#34;UTF-8&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;LC_MESSAGES=&amp;#34;C&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;LC_MONETARY=&amp;#34;C&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;LC_NUMERIC=&amp;#34;C&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;LC_TIME=&amp;#34;C&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;LC_ALL=&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;環境変数の確認も行う。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;env | grep -E &amp;#34;(LANG|LC_)&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドで表示される内容と&lt;code&gt;locale&lt;/code&gt;コマンドの出力に不一致がある場合、設定の競合が発生している可能性が高い。&lt;/p&gt;&#10;&lt;h3 id="根本原因の推定"&gt;根本原因の推定&#10;&lt;/h3&gt;&lt;p&gt;警告メッセージの&lt;code&gt;cannot change locale ():&lt;/code&gt;の括弧内が空になっているのは、どこかでロケール関連の環境変数が空文字列に設定されているためである。これは以下のような要因で発生する可能性がある。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;以前使用していたシェル（fish等）の設定残骸&lt;/li&gt;&#10;&lt;li&gt;システムアップデート時の設定の不整合&lt;/li&gt;&#10;&lt;li&gt;複数のツールによる環境変数の競合&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="解決方法"&gt;解決方法&#10;&lt;/h2&gt;&lt;h3 id="基本的な対症療法"&gt;基本的な対症療法&#10;&lt;/h3&gt;&lt;p&gt;個人用の設定ファイルを作成し、明示的にロケールを設定する。これにより、不完全な設定を上書きできる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;echo &amp;#39;export LANG=en_US.UTF-8&amp;#39; &amp;gt; ~/.bash_profile&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;設定を即座に反映させる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;source ~/.bash_profile&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="設定内容の選択指針"&gt;設定内容の選択指針&#10;&lt;/h3&gt;&lt;p&gt;ロケール設定には以下の選択肢がある。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;英語環境での自然な並び順を優先する場合（推奨）&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;export LANG=en_US.UTF-8&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この設定により、&lt;code&gt;ls&lt;/code&gt;コマンドやファイルソートで大文字小文字を考慮した辞書順になる。具体的には、&lt;code&gt;Apple&lt;/code&gt;、&lt;code&gt;apple&lt;/code&gt;、&lt;code&gt;Banana&lt;/code&gt;、&lt;code&gt;banana&lt;/code&gt;の順序で表示される。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;純粋なASCII順序を優先する場合&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;export LANG=C&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この設定では、ASCII値順（数字→大文字→小文字）でソートされる。プログラマー向けの厳密な順序だが、一般的な用途では直感的でない順序になることがある。&lt;/p&gt;&#10;&lt;h3 id="設定の確認"&gt;設定の確認&#10;&lt;/h3&gt;&lt;p&gt;設定後、新しいターミナルを開いて以下を確認する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;locale&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;すべての&lt;code&gt;LC_*&lt;/code&gt;項目が設定したロケール（例：&lt;code&gt;en_US.UTF-8&lt;/code&gt;）になっていれば成功である。また、警告メッセージが表示されなくなることを確認する。&lt;/p&gt;&#10;&lt;h2 id="追加の対処法"&gt;追加の対処法&#10;&lt;/h2&gt;&lt;h3 id="ターミナルアプリ固有の設定確認"&gt;ターミナルアプリ固有の設定確認&#10;&lt;/h3&gt;&lt;p&gt;一部のターミナルアプリケーションは独自の設定ファイルを持つ場合がある。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;#34;/etc/bashrc_$TERM_PROGRAM&amp;#34; 2&amp;gt;/dev/null || echo &amp;#34;Terminal-specific bashrc not found&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="利用可能なロケールの確認"&gt;利用可能なロケールの確認&#10;&lt;/h3&gt;&lt;p&gt;システムでサポートされているロケールを確認したい場合は以下を実行する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;locale -a | grep -E &amp;#34;(en_US|ja_JP|C$)&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="注意事項"&gt;注意事項&#10;&lt;/h2&gt;&lt;p&gt;この方法は対症療法であり、根本的な原因（どこで空文字列が設定されているか）を解決するものではない。しかし、実用上は十分な解決策となる。&lt;/p&gt;&#10;&lt;p&gt;長期間使用しているシステムでは、様々なツールのインストール・アンインストールにより設定の断片が残存することがある。完全な解決を求める場合は、クリーンインストールが最も確実な方法である。&lt;/p&gt;&#10;&lt;h2 id="参考資料"&gt;参考資料&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://www.gnu.org/software/bash/manual/" target="_blank" rel="noopener"&#10; &gt;Bashマニュアル - GNU&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/" target="_blank" rel="noopener"&#10; &gt;ロケール設定 - Apple Developer Documentation&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>Giteaへの既存コードpushでrejectedエラーを解決する方法</title><link>https://ai.hack-le.com/gitea%E3%81%B8%E3%81%AE%E6%97%A2%E5%AD%98%E3%82%B3%E3%83%BC%E3%83%89push%E3%81%A7rejected%E3%82%A8%E3%83%A9%E3%83%BC%E3%82%92%E8%A7%A3%E6%B1%BA%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</link><pubDate>Thu, 11 Sep 2025 17:45:22 +0900</pubDate><guid>https://ai.hack-le.com/gitea%E3%81%B8%E3%81%AE%E6%97%A2%E5%AD%98%E3%82%B3%E3%83%BC%E3%83%89push%E3%81%A7rejected%E3%82%A8%E3%83%A9%E3%83%BC%E3%82%92%E8%A7%A3%E6%B1%BA%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</guid><description>&lt;p&gt;既存のローカルプロジェクトをGiteaサーバーにpushしようとした際、「Updates were rejected because the remote contains work that you do not have locally」エラーが発生した。このエラーの原因と解決方法について記録する。&lt;/p&gt;&#10;&lt;h2 id="再現環境"&gt;再現環境&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;ローカル環境：macOS&lt;/li&gt;&#10;&lt;li&gt;Git：既存のローカルリポジトリ（masterブランチ）&lt;/li&gt;&#10;&lt;li&gt;リモート：Giteaサーバー（プライベートネットワーク内）&lt;/li&gt;&#10;&lt;li&gt;接続方式：SSH&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="エラーの発生状況"&gt;エラーの発生状況&#10;&lt;/h2&gt;&lt;p&gt;実行したコマンド&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# リモートリポジトリを追加&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git remote add origin user@xxx.xxx.xxx.xxx:org/repository-name.git&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# pushを実行&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git push -u origin master&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;発生したエラー&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To xxx.xxx.xxx.xxx:org/repository-name.git&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ! [rejected] master -&amp;gt; master (fetch first)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;error: failed to push some refs to &amp;#39;xxx.xxx.xxx.xxx:org/repository-name.git&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hint: Updates were rejected because the remote contains work that you do not&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hint: have locally. This is usually caused by another repository pushing to&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hint: the same ref. If you want to integrate the remote changes, use&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hint: &amp;#39;git pull&amp;#39; before pushing again.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hint: See the &amp;#39;Note about fast-forwards&amp;#39; in &amp;#39;git push --help&amp;#39; for details.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="エラーの原因分析"&gt;エラーの原因分析&#10;&lt;/h2&gt;&lt;p&gt;このエラーが発生する主な原因は、リモートリポジトリとローカルリポジトリの履歴が一致していないことである。具体的には以下のケースが考えられる。&lt;/p&gt;&#10;&lt;h3 id="最も一般的な原因"&gt;最も一般的な原因&#10;&lt;/h3&gt;&lt;p&gt;Giteaでリポジトリを作成する際に「Initialize with README」オプションを有効にしたため、リモートリポジトリに初期コミット（README.md）が存在していた。一方、ローカルでは既存のプロジェクトを独立してgit管理していたため、両者に共通の祖先コミットが存在しない状態となった。&lt;/p&gt;&#10;&lt;h3 id="その他の原因"&gt;その他の原因&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;他の開発者が既にコミットをプッシュしている&lt;/li&gt;&#10;&lt;li&gt;複数の場所から同じリポジトリにプッシュを試行している&lt;/li&gt;&#10;&lt;li&gt;リモートリポジトリが予期せず変更されている&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="解決方法"&gt;解決方法&#10;&lt;/h2&gt;&lt;h3 id="手順1-リモートの変更を確認"&gt;手順1: リモートの変更を確認&#10;&lt;/h3&gt;&lt;p&gt;まず、リモートにどのような変更があるかを確認する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git fetch origin&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git log origin/master --oneline&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="手順2-無関係な履歴をマージしてpull"&gt;手順2: 無関係な履歴をマージしてpull&#10;&lt;/h3&gt;&lt;p&gt;以下のコマンドを実行して、無関係な履歴を統合する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git pull origin master --allow-unrelated-histories --no-rebase&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="手順3-競合の解決必要な場合"&gt;手順3: 競合の解決（必要な場合）&#10;&lt;/h3&gt;&lt;p&gt;README.mdなどでマージ競合が発生した場合は、手動で解決する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 競合ファイルを編集後&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &amp;#34;Resolve merge conflicts&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="手順4-最終的なpush"&gt;手順4: 最終的なpush&#10;&lt;/h3&gt;&lt;p&gt;競合を解決できたら、改めてpushを実行する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git push origin master&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="予防方法"&gt;予防方法&#10;&lt;/h2&gt;&lt;p&gt;既存コードをpushする予定がある場合は、Giteaでリポジトリを作成する際に以下の自動生成オプションを無効にする。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;README.mdの自動生成&lt;/li&gt;&#10;&lt;li&gt;.gitignoreの自動生成&lt;/li&gt;&#10;&lt;li&gt;ライセンスファイルの自動生成&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;新規プロジェクトを開始する場合は、以下の手順を推奨する。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Giteaで空のリポジトリを作成&lt;/li&gt;&#10;&lt;li&gt;ローカルでgit cloneを実行&lt;/li&gt;&#10;&lt;li&gt;cloneしたディレクトリ内で開発を開始&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;この方法により、最初から履歴が一致した状態で開発を進められる。&lt;/p&gt;&#10;&lt;h2 id="技術的背景"&gt;技術的背景&#10;&lt;/h2&gt;&lt;h3 id="allow-unrelated-historiesオプションについて"&gt;&amp;ndash;allow-unrelated-historiesオプションについて&#10;&lt;/h3&gt;&lt;p&gt;Gitは通常、共通の祖先を持たないブランチ同士のマージを拒否する。&lt;code&gt;--allow-unrelated-histories&lt;/code&gt;オプションは、この制限を解除して無関係な履歴同士をマージすることを可能にする。&lt;/p&gt;&#10;&lt;h3 id="プルストラテジーの選択"&gt;プルストラテジーの選択&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;git pull&lt;/code&gt;コマンド実行時に以下のエラーが発生する場合がある。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hint: You have divergent branches and need to specify how to reconcile them.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この場合は、マージ戦略を明示的に指定する必要がある。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# マージ戦略を使用（推奨）&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git pull origin master --allow-unrelated-histories --no-rebase&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# またはリベース戦略を使用&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git pull origin master --allow-unrelated-histories --rebase&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;マージ戦略を選択することで、両方の履歴が保持されたマージコミットが作成される。&lt;/p&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;このエラーは、Git初心者が既存コードをリモートリポジトリにpushする際によく遭遇する問題である。根本的な原因は履歴の不一致であり、&lt;code&gt;--allow-unrelated-histories&lt;/code&gt;オプションを使用することで解決できる。&lt;/p&gt;&#10;&lt;p&gt;今後は、リポジトリ作成時の設定に注意を払い、適切なワークフローを選択することで、このような問題を予防できる。特に、既存プロジェクトをGitで管理し始める際は、リモートリポジトリを完全に空の状態で作成することが重要である。&lt;/p&gt;&#10;</description></item><item><title>WSL環境でMac風のpbcopy/pbpasteを実現する方法</title><link>https://ai.hack-le.com/wsl%E7%92%B0%E5%A2%83%E3%81%A7mac%E9%A2%A8%E3%81%AEpbcopy-pbpaste%E3%82%92%E5%AE%9F%E7%8F%BE%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</link><pubDate>Sun, 17 Aug 2025 13:47:19 +0900</pubDate><guid>https://ai.hack-le.com/wsl%E7%92%B0%E5%A2%83%E3%81%A7mac%E9%A2%A8%E3%81%AEpbcopy-pbpaste%E3%82%92%E5%AE%9F%E7%8F%BE%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/</guid><description>&lt;h2 id="前提環境"&gt;前提環境&#10;&lt;/h2&gt;&lt;p&gt;この記事は以下の環境での動作を前提としている。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Windows 10/11&lt;/li&gt;&#10;&lt;li&gt;WSL2（Windows Subsystem for Linux 2）&lt;/li&gt;&#10;&lt;li&gt;Ubuntu 20.04以降（他のディストリビューションでも同様の手順で可能）&lt;/li&gt;&#10;&lt;li&gt;Bash または Zsh シェル&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="背景と課題"&gt;背景と課題&#10;&lt;/h2&gt;&lt;p&gt;Macユーザーであれば、コマンドラインからクリップボードを操作する際に&lt;code&gt;pbcopy&lt;/code&gt;と&lt;code&gt;pbpaste&lt;/code&gt;コマンドを使用することに慣れているだろう。これらのコマンドは非常に便利で、パイプを使ってテキストをクリップボードにコピーしたり、クリップボードの内容を取得したりできる。&lt;/p&gt;&#10;&lt;p&gt;一方、WSL環境では標準でこのような機能は提供されていない。Linux用のクリップボードツールである&lt;code&gt;xclip&lt;/code&gt;をインストールしても、これはX Window System内でのクリップボード操作に留まり、Windowsのシステムクリップボードとは連携しない。つまり、WSL内で&lt;code&gt;xclip&lt;/code&gt;を使ってコピーした内容を、Windows側のアプリケーションで貼り付けることはできないのである。&lt;/p&gt;&#10;&lt;h2 id="windowsのネイティブなクリップボードapi"&gt;WindowsのネイティブなクリップボードAPI&#10;&lt;/h2&gt;&lt;p&gt;実は、Windowsには&lt;code&gt;clip.exe&lt;/code&gt;というコマンドラインツールが標準で付属している。このツールを使用することで、パイプ経由でテキストをクリップボードに書き込むことが可能である。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;echo &amp;#34;Hello World&amp;#34; | clip.exe&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上記のコマンドを実行すると、「Hello World」がWindowsのクリップボードにコピーされ、任意のWindowsアプリケーションで貼り付けることができる。&lt;/p&gt;&#10;&lt;p&gt;ただし、&lt;code&gt;clip.exe&lt;/code&gt;は書き込み専用であり、クリップボードの内容を読み取る機能は提供されていない。そのため、Macの&lt;code&gt;pbpaste&lt;/code&gt;に相当する機能を実現するには別の方法が必要となる。&lt;/p&gt;&#10;&lt;h2 id="powershellを活用したクリップボード読み取り"&gt;PowerShellを活用したクリップボード読み取り&#10;&lt;/h2&gt;&lt;p&gt;Windowsでクリップボードの内容を取得するには、PowerShellの&lt;code&gt;Get-Clipboard&lt;/code&gt;コマンドレットを使用する。WSL内からPowerShellを呼び出すことで、この機能を利用できる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;powershell.exe -command &amp;#34;Get-Clipboard&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドを実行すると、現在のクリップボードの内容がターミナルに出力される。なお、&lt;code&gt;-command&lt;/code&gt;パラメータは省略可能であり、以下のように短縮して記述することも可能である。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;powershell.exe &amp;#34;Get-Clipboard&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="エイリアスによる利便性の向上"&gt;エイリアスによる利便性の向上&#10;&lt;/h2&gt;&lt;p&gt;毎回長いコマンドを入力するのは非効率的であるため、エイリアスを設定してMacと同様の使い勝手を実現する。使用しているシェルの設定ファイル（Bashの場合は&lt;code&gt;~/.bashrc&lt;/code&gt;、Zshの場合は&lt;code&gt;~/.zshrc&lt;/code&gt;）に以下の行を追加する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alias pbcopy=&amp;#39;clip.exe&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alias pbpaste=&amp;#39;powershell.exe -command &amp;#34;Get-Clipboard&amp;#34;&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;設定を反映するために、シェルを再起動するか、以下のコマンドを実行する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Bashの場合&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;source ~/.bashrc&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Zshの場合 &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;source ~/.zshrc&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="実際の使用例"&gt;実際の使用例&#10;&lt;/h2&gt;&lt;p&gt;エイリアスを設定した後は、Macと同様の感覚でクリップボード操作が可能になる。以下に実用的な使用例を示す。&lt;/p&gt;&#10;&lt;h3 id="基本的な使用方法"&gt;基本的な使用方法&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# テキストをクリップボードにコピー&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;echo &amp;#34;テスト文字列&amp;#34; | pbcopy&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# クリップボードの内容を表示&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pbpaste&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ファイルの内容をクリップボードにコピー"&gt;ファイルの内容をクリップボードにコピー&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# SSH公開鍵をクリップボードにコピー（GitHubへの登録などに便利）&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat ~/.ssh/id_rsa.pub | pbcopy&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 設定ファイルの内容をクリップボードにコピー&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat ~/.vimrc | pbcopy&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="gitとの連携"&gt;Gitとの連携&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 最新5件のコミット履歴をクリップボードにコピー&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git log --oneline -5 | pbcopy&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 現在のブランチ名をクリップボードにコピー&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git branch --show-current | pbcopy&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 現在のリモートURLをクリップボードにコピー&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git remote get-url origin | pbcopy&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ディレクトリパスの活用"&gt;ディレクトリパスの活用&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 現在のディレクトリパスをクリップボードにコピー&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pwd | pbcopy&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 特定のファイルの絶対パスをクリップボードにコピー&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;readlink -f example.txt | pbcopy&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="パフォーマンスと制限事項"&gt;パフォーマンスと制限事項&#10;&lt;/h2&gt;&lt;p&gt;このアプローチにはいくつかの注意点がある。まず、&lt;code&gt;powershell.exe&lt;/code&gt;の起動には若干の時間がかかるため、&lt;code&gt;pbpaste&lt;/code&gt;の実行速度は純粋なLinuxコマンドと比較して遅くなる。ただし、日常的な使用においては実用上問題となることは少ない。&lt;/p&gt;&#10;&lt;p&gt;また、非常に大きなテキストをクリップボードに格納する場合、PowerShellの制限によって一部のデータが切り取られる可能性がある。通常の開発作業で扱うテキストサイズであれば問題ないが、大容量のデータを扱う場合は注意が必要である。&lt;/p&gt;&#10;&lt;p&gt;さらに、この方法はWSLからWindowsの実行ファイルを呼び出すため、WSL2の場合はネットワークを介した通信が発生する。セキュリティ設定によっては、この通信が制限される可能性もある。&lt;/p&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;WSL環境においても、Windowsの標準機能とPowerShellを組み合わせることで、Macの&lt;code&gt;pbcopy&lt;/code&gt;/&lt;code&gt;pbpaste&lt;/code&gt;と同等の機能を実現できる。エイリアスを設定することで、Macからの移行時も違和感なく使用できるようになる。&lt;/p&gt;&#10;&lt;p&gt;この方法の最大の利点は、追加のソフトウェアをインストールすることなく、Windowsの標準機能のみで実現できることである。WSLでの開発効率を向上させる簡単で実用的な設定として、ぜひ活用していただきたい。&lt;/p&gt;&#10;</description></item><item><title>LinuxでmacOS風クリップボード操作を実現するxclipの設定方法</title><link>https://ai.hack-le.com/linux%E3%81%A7macos%E9%A2%A8%E3%82%AF%E3%83%AA%E3%83%83%E3%83%97%E3%83%9C%E3%83%BC%E3%83%89%E6%93%8D%E4%BD%9C%E3%82%92%E5%AE%9F%E7%8F%BE%E3%81%99%E3%82%8Bxclip%E3%81%AE%E8%A8%AD%E5%AE%9A%E6%96%B9/</link><pubDate>Sat, 09 Aug 2025 20:03:51 +0900</pubDate><guid>https://ai.hack-le.com/linux%E3%81%A7macos%E9%A2%A8%E3%82%AF%E3%83%AA%E3%83%83%E3%83%97%E3%83%9C%E3%83%BC%E3%83%89%E6%93%8D%E4%BD%9C%E3%82%92%E5%AE%9F%E7%8F%BE%E3%81%99%E3%82%8Bxclip%E3%81%AE%E8%A8%AD%E5%AE%9A%E6%96%B9/</guid><description>&lt;p&gt;この記事の内容は、X11ウィンドウシステムを使用するLinux環境で動作確認している。Wayland環境では&lt;code&gt;wl-clipboard&lt;/code&gt;パッケージを使用する必要があるため、事前に使用環境を確認してほしい。また、記事中のコマンド例は、Debian/Ubuntu系ディストリビューションでの実行を前提としている。&lt;/p&gt;&#10;&lt;h2 id="linuxでのcliクリップボード操作の必要性"&gt;LinuxでのCLIクリップボード操作の必要性&#10;&lt;/h2&gt;&lt;p&gt;Linuxでコマンドライン作業をしていると、コマンドの出力結果をブラウザやテキストエディタに貼り付けたい場面が頻繁にある。しかし、標準的なLinux環境では、ターミナル出力を直接システムクリップボードに送る機能が用意されていない。一方、macOSでは&lt;code&gt;pbcopy&lt;/code&gt;と&lt;code&gt;pbpaste&lt;/code&gt;コマンドが標準で提供されており、パイプを使って簡単にクリップボード操作ができる。Linuxでも同様の機能を実現するためのツールが&lt;code&gt;xclip&lt;/code&gt;である。&lt;/p&gt;&#10;&lt;p&gt;xclipは、X11環境でコマンドライン出力をシステムクリップボードに送ったり、クリップボードの内容をターミナルに出力したりできる軽量なユーティリティである。このツールを適切に設定することで、macOSと同じような感覚でクリップボード操作を行うことができる。&lt;/p&gt;&#10;&lt;h2 id="xclipのインストール手順"&gt;xclipのインストール手順&#10;&lt;/h2&gt;&lt;p&gt;xclipのインストール方法は、使用しているLinuxディストリビューションによって異なる。主要なディストリビューションでの手順を以下に示す。&lt;/p&gt;&#10;&lt;p&gt;Debian系（Ubuntu、Linux Mint等）では、aptパッケージマネージャーを使用してインストールできる。まずパッケージリストを更新してから、xclipパッケージをインストールする。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install xclip&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Red Hat系（CentOS、RHEL、Fedora等）では、使用しているバージョンに応じてyumまたはdnfを使用する。Fedoraの場合は以下のコマンドでインストールできる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo dnf install xclip&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;CentOS 7やRHEL 7の場合は、EPELリポジトリを有効にしてからインストールする必要がある。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum install epel-release&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum install xclip&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Arch Linuxでは、pacmanパッケージマネージャーを使用してインストールできる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo pacman -S xclip&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;インストールが完了したら、簡単なテストを行ってxclipが正常に動作することを確認する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;echo &amp;#34;test message&amp;#34; | xclip -selection clipboard&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドを実行後、テキストエディタやブラウザでCtrl+Vを押して「test message」が貼り付けられれば、インストールは成功している。&lt;/p&gt;&#10;&lt;h2 id="xclipの基本的な使用方法"&gt;xclipの基本的な使用方法&#10;&lt;/h2&gt;&lt;p&gt;xclipを使用してクリップボード操作を行う場合、主に&lt;code&gt;-selection clipboard&lt;/code&gt;オプションを使用する。このオプションを指定することで、一般的なアプリケーションでCtrl+C/Ctrl+Vで使用するクリップボードにアクセスできる。&lt;/p&gt;&#10;&lt;p&gt;コマンド出力をクリップボードにコピーする場合は、パイプを使ってxclipに出力を渡す。例えば、現在のディレクトリの詳細なファイル一覧をクリップボードにコピーしたい場合は、以下のコマンドを使用する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls -la | xclip -selection clipboard&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ファイルの内容をクリップボードにコピーしたい場合は、リダイレクションを使用する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;xclip -selection clipboard &amp;lt; file.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;クリップボードの内容を表示したい場合は、&lt;code&gt;-o&lt;/code&gt;オプション（出力オプション）を使用する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;xclip -selection clipboard -o&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;-selection clipboard&lt;/code&gt;は頻繁に使用するため、&lt;code&gt;-sel clip&lt;/code&gt;と短縮形で記述することも可能である。&lt;/p&gt;&#10;&lt;h2 id="macos風エイリアスの設定方法"&gt;macOS風エイリアスの設定方法&#10;&lt;/h2&gt;&lt;p&gt;MacとLinuxの両方を使用している場合、同じコマンドでクリップボード操作ができると非常に便利である。macOSの&lt;code&gt;pbcopy&lt;/code&gt;と&lt;code&gt;pbpaste&lt;/code&gt;コマンドと同じ感覚で使用できるように、bashまたはzshの設定ファイルにエイリアスを追加する。&lt;/p&gt;&#10;&lt;p&gt;bashを使用している場合は、ホームディレクトリの&lt;code&gt;.bashrc&lt;/code&gt;ファイルに以下の行を追加する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alias pbcopy=&amp;#39;xclip -selection clipboard&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alias pbpaste=&amp;#39;xclip -selection clipboard -o&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;zshを使用している場合は、&lt;code&gt;.zshrc&lt;/code&gt;ファイルに同じ内容を追加する。設定を手動で編集するか、以下のコマンドで一括追加できる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;echo &amp;#39;alias pbcopy=&amp;#34;xclip -selection clipboard&amp;#34;&amp;#39; &amp;gt;&amp;gt; ~/.bashrc&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;echo &amp;#39;alias pbpaste=&amp;#34;xclip -selection clipboard -o&amp;#34;&amp;#39; &amp;gt;&amp;gt; ~/.bashrc&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;source ~/.bashrc&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;設定後は、macOSと全く同じコマンドでクリップボード操作が可能になる。&lt;/p&gt;&#10;&lt;h2 id="実際の活用例"&gt;実際の活用例&#10;&lt;/h2&gt;&lt;p&gt;エイリアス設定後の具体的な活用例をいくつか紹介する。これらの例は、日常的な開発作業で頻繁に使用する場面である。&lt;/p&gt;&#10;&lt;p&gt;ファイルの内容をクリップボードにコピーする場合：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pbcopy &amp;lt; config.json&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コマンド実行結果をクリップボードにコピーする場合：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git log --oneline --graph | pbcopy&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;システム情報をクリップボードにコピーする場合：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uname -a | pbcopy&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;クリップボードの内容をファイルに保存する場合：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pbpaste &amp;gt; output.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;SSH公開鍵をクリップボードにコピーする場合：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pbcopy &amp;lt; ~/.ssh/id_rsa.pub&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これらの例のように、パイプやリダイレクションと組み合わせることで、様々な場面でクリップボード操作を活用できる。特に、長いコマンド出力やファイル内容を他のアプリケーションに貼り付ける際に、マウス操作によるコピー&amp;amp;ペーストよりも効率的である。&lt;/p&gt;&#10;&lt;h2 id="その他のクリップボードツールとの比較"&gt;その他のクリップボードツールとの比較&#10;&lt;/h2&gt;&lt;p&gt;X11環境でのクリップボード操作ツールとしては、xclip以外にも&lt;code&gt;xsel&lt;/code&gt;がある。xselも同様の機能を提供するが、xclipの方が一般的に広く使用されており、ドキュメントやコミュニティサポートが充実している。また、パッケージマネージャーでの提供状況もxclipの方が良好である。&lt;/p&gt;&#10;&lt;p&gt;Wayland環境を使用している場合は、&lt;code&gt;wl-clipboard&lt;/code&gt;パッケージの&lt;code&gt;wl-copy&lt;/code&gt;と&lt;code&gt;wl-paste&lt;/code&gt;コマンドを使用する必要がある。使用方法はxclipと類似しているが、オプションの指定方法が異なるため注意が必要である。&lt;/p&gt;&#10;&lt;p&gt;現在の環境がX11かWaylandかを確認するには、以下のコマンドを実行する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;echo $XDG_SESSION_TYPE&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;出力が「x11」であればxclipを、「wayland」であればwl-clipboardを使用することを推奨する。&lt;/p&gt;&#10;&lt;p&gt;この設定により、LinuxとmacOSの間での作業環境の切り替えが円滑になり、クリップボード操作に関する認知的負荷を軽減できる。特に、複数のOSを使い分けている開発者にとっては、コマンドの統一性が作業効率の向上に大きく貢献する。&lt;/p&gt;&#10;</description></item><item><title>AWKを使った簡単な合計計算の方法</title><link>https://ai.hack-le.com/awk-sum/</link><pubDate>Thu, 19 Dec 2024 11:02:34 +0900</pubDate><guid>https://ai.hack-le.com/awk-sum/</guid><description>&lt;p&gt;AWKはテキスト処理に非常に便利なツールであり、数値の合計を簡単に計算する方法を備えています。本記事では、AWKを使用して数値の合計を求める方法について解説します。&lt;/p&gt;&#10;&lt;h2 id="背景"&gt;背景&#10;&lt;/h2&gt;&lt;p&gt;シェルスクリプトやコマンドラインで処理するデータには、数値が複数行にわたって出力されることがよくあります。例えば、以下のような出力があるとします：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;64&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;65&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;71&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;82&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;82&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;79&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これらの数値の合計を求める必要がある場合、AWKを使うことで簡単に処理できます。&lt;/p&gt;&#10;&lt;h2 id="基本コマンド"&gt;基本コマンド&#10;&lt;/h2&gt;&lt;p&gt;以下のコマンドを使用すると、入力データの合計を計算できます：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &amp;#39;{sum += $1} END {print sum}&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="コマンドの仕組み"&gt;コマンドの仕組み&#10;&lt;/h3&gt;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;code&gt;{sum += $1}&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;各行の1列目（&lt;code&gt;$1&lt;/code&gt;）を変数&lt;code&gt;sum&lt;/code&gt;に加算します。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;sum&lt;/code&gt;は最初に自動的に0で初期化されます。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;ol start="2"&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;code&gt;END {print sum}&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;すべての行を処理し終えた後に&lt;code&gt;END&lt;/code&gt;ブロックが実行され、合計値&lt;code&gt;sum&lt;/code&gt;を出力します。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="実例"&gt;実例&#10;&lt;/h2&gt;&lt;h3 id="データの例"&gt;データの例&#10;&lt;/h3&gt;&lt;p&gt;以下のような数値データを持つファイル&lt;code&gt;data.txt&lt;/code&gt;があるとします：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;64&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;65&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;71&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;82&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;82&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;79&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このファイルの合計を計算するには、以下のコマンドを実行します：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat data.txt | awk &amp;#39;{sum += $1} END {print sum}&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="出力結果"&gt;出力結果&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;443&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="findコマンドとの組み合わせ"&gt;&lt;code&gt;find&lt;/code&gt;コマンドとの組み合わせ&#10;&lt;/h3&gt;&lt;p&gt;複数のJSONファイルに対してPythonスクリプトを実行し、その結果の合計を求めるケースを考えます。&lt;/p&gt;&#10;&lt;p&gt;以下のコマンドを使用します：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -name &amp;#34;*.json&amp;#34; -exec python a.py {} \; | awk &amp;#39;{sum += $1} END {print sum}&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;&#10;&lt;li&gt;&lt;code&gt;find&lt;/code&gt;コマンドで&lt;code&gt;.json&lt;/code&gt;ファイルを検索。&lt;/li&gt;&#10;&lt;li&gt;各ファイルに対して&lt;code&gt;python a.py&lt;/code&gt;を実行。&lt;/li&gt;&#10;&lt;li&gt;AWKで出力結果を集計し、合計値を出力。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h3 id="出力例"&gt;出力例&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1445&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="応用例"&gt;応用例&#10;&lt;/h2&gt;&lt;p&gt;AWKの&lt;code&gt;sum&lt;/code&gt;変数を応用して、さまざまな計算が可能です：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;平均値の計算&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &amp;#39;{sum += $1; count++} END {print sum / count}&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;最大値と最小値の計算&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &amp;#39;NR == 1 || $1 &amp;gt; max {max = $1} NR == 1 || $1 &amp;lt; min {min = $1} END {print &amp;#34;Max:&amp;#34;, max, &amp;#34;Min:&amp;#34;, min}&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;AWKはシンプルな構文で強力なテキスト処理を可能にするツールです。特に数値データの合計計算は、短いコマンドで簡単に実現できます。ぜひ活用してみてください！&lt;/p&gt;&#10;</description></item><item><title>[Linux] 一時的にスワップファイルを作成する</title><link>https://ai.hack-le.com/linux-swap-temp/</link><pubDate>Wed, 20 Nov 2024 18:18:16 +0900</pubDate><guid>https://ai.hack-le.com/linux-swap-temp/</guid><description>&lt;p&gt;ビルド時や一時的な高負荷作業でメモリ不足が発生する場合、スワップファイルを一時的に追加することで問題を回避できます。本記事では、一時的なスワップファイルを作成して使用し、作業終了後に削除する手順と、それを効率化するスクリプトをご紹介します。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="スワップファイルとは"&gt;スワップファイルとは？&#10;&lt;/h2&gt;&lt;p&gt;スワップファイルは、物理メモリが不足した際にディスク上の領域を仮想メモリとして利用する仕組みです。ただし、ディスクはメモリよりも遅いため、スワップの使用頻度が高いとパフォーマンスに影響を及ぼす可能性があります。そのため、一時的にスワップを増やして高負荷作業を乗り切り、作業終了後に削除する運用が適しています。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="一時的なスワップファイルを作成する手順"&gt;一時的なスワップファイルを作成する手順&#10;&lt;/h2&gt;&lt;h3 id="1-一時的なスワップファイルを作成"&gt;1. 一時的なスワップファイルを作成&#10;&lt;/h3&gt;&lt;p&gt;以下のコマンドで、4GBのスワップファイルを作成します（サイズは用途に応じて変更可能）。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo fallocate -l 4G /tmp/swapfile_temp&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;💡 &lt;code&gt;fallocate&lt;/code&gt;が使用できない場合は、以下のコマンドを使用します:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo dd if=/dev/zero of=/tmp/swapfile_temp bs=1M count=4096&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;h3 id="2-ファイルの権限を設定"&gt;2. ファイルの権限を設定&#10;&lt;/h3&gt;&lt;p&gt;スワップファイルのセキュリティを確保するため、600の権限を設定します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo chmod 600 /tmp/swapfile_temp&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;h3 id="3-スワップファイルを有効化"&gt;3. スワップファイルを有効化&#10;&lt;/h3&gt;&lt;p&gt;スワップファイルをスワップ領域としてフォーマットし、有効化します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo mkswap /tmp/swapfile_temp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo swapon /tmp/swapfile_temp&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-スワップ状況を確認"&gt;4. スワップ状況を確認&#10;&lt;/h3&gt;&lt;p&gt;現在のスワップ領域を確認して、追加されたスワップが有効になっているか確認します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;swapon --show&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;h3 id="5-作業を実行"&gt;5. 作業を実行&#10;&lt;/h3&gt;&lt;p&gt;ビルドや高負荷の処理を実行します。スワップが有効になっていることで、メモリ不足によるプロセスの停止を回避できます。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h3 id="6-スワップファイルを無効化"&gt;6. スワップファイルを無効化&#10;&lt;/h3&gt;&lt;p&gt;作業が終了したら、以下のコマンドでスワップファイルを無効化します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo swapoff /tmp/swapfile_temp&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;h3 id="7-スワップファイルを削除"&gt;7. スワップファイルを削除&#10;&lt;/h3&gt;&lt;p&gt;スワップファイルを削除してディスク容量を解放します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo rm /tmp/swapfile_temp&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;h2 id="一時的なスワップファイルを効率化するスクリプト"&gt;一時的なスワップファイルを効率化するスクリプト&#10;&lt;/h2&gt;&lt;p&gt;毎回コマンドを入力するのが手間な場合、スクリプトを作成することで効率化できます。以下のスクリプトは、一時的なスワップを追加・削除する機能を提供します。&lt;/p&gt;&#10;&lt;h3 id="スクリプト-temporary_swapsh"&gt;スクリプト: &lt;code&gt;temporary_swap.sh&lt;/code&gt;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;SWAPFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/tmp/swapfile_temp&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;SIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;4G&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;add&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Adding temporary swap file...&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sudo fallocate -l &lt;span class="nv"&gt;$SIZE&lt;/span&gt; &lt;span class="nv"&gt;$SWAPFILE&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sudo chmod &lt;span class="m"&gt;600&lt;/span&gt; &lt;span class="nv"&gt;$SWAPFILE&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sudo mkswap &lt;span class="nv"&gt;$SWAPFILE&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sudo swapon &lt;span class="nv"&gt;$SWAPFILE&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Temporary swap file added.&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;remove&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Removing temporary swap file...&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sudo swapoff &lt;span class="nv"&gt;$SWAPFILE&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sudo rm &lt;span class="nv"&gt;$SWAPFILE&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Temporary swap file removed.&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt; {add|remove}&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;h3 id="スクリプトの使い方"&gt;スクリプトの使い方&#10;&lt;/h3&gt;&lt;ol&gt;&#10;&lt;li&gt;スクリプトを作成して実行権限を付与します。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod +x temporary_swap.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;&#10;&lt;li&gt;スワップファイルを追加するには、以下のコマンドを実行します。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./temporary_swap.sh add&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;&#10;&lt;li&gt;スワップファイルを削除するには、以下を実行します。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./temporary_swap.sh remove&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;一時的なスワップファイルを作成して高負荷作業を安全に乗り切ることができます。&lt;/li&gt;&#10;&lt;li&gt;作業が終了したらスワップファイルを削除することで、ディスク容量を無駄にせずに運用できます。&lt;/li&gt;&#10;&lt;li&gt;スクリプトを活用することで、日々の作業を効率化できます。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;一時的なスワップファイルの運用は、VPSのようにリソースが限られた環境で特に有効です。ぜひお試しください！&lt;/p&gt;&#10;</description></item><item><title>VSCodeでリモートサーバーのコードをSSH経由で編集する方法</title><link>https://ai.hack-le.com/vscode-remote-ssh/</link><pubDate>Wed, 20 Nov 2024 16:36:45 +0900</pubDate><guid>https://ai.hack-le.com/vscode-remote-ssh/</guid><description>&lt;p&gt;リモートサーバー上のコードをVSCodeで直接編集したいとき、「Remote - SSH」拡張機能を使えば簡単に設定できます。この記事では、その手順を初心者向けにわかりやすく解説します。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="-前提条件"&gt;📌 前提条件&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;VSCode&lt;/strong&gt;がインストールされていること。&lt;/li&gt;&#10;&lt;li&gt;SSHでリモートサーバーにアクセスできること（公開鍵認証またはパスワード認証）。&lt;/li&gt;&#10;&lt;li&gt;インターネット接続があること。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="-手順"&gt;📖 手順&#10;&lt;/h2&gt;&lt;h3 id="1-remote---ssh拡張機能をインストール"&gt;1. 「Remote - SSH」拡張機能をインストール&#10;&lt;/h3&gt;&lt;ol&gt;&#10;&lt;li&gt;VSCodeを起動します。&lt;/li&gt;&#10;&lt;li&gt;左側の「拡張機能」アイコン（四角が飛び出すマーク）をクリックします。&lt;/li&gt;&#10;&lt;li&gt;検索バーに「Remote - SSH」と入力。&lt;/li&gt;&#10;&lt;li&gt;Microsoft製の「Remote - SSH」拡張機能をインストールします。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;hr&gt;&#10;&lt;h3 id="2-ssh設定ファイルの準備"&gt;2. SSH設定ファイルの準備&#10;&lt;/h3&gt;&lt;p&gt;SSH接続には、&lt;code&gt;~/.ssh/config&lt;/code&gt;ファイルを使用します。この設定ファイルでリモートサーバーへの接続を定義します。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;ターミナルを開き、以下のコマンドを実行して設定ファイルを作成または編集します:&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nano ~/.ssh/config&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;&#10;&lt;li&gt;以下のように、リモートサーバーの情報を記述します:&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Host my-remote-server&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; HostName 192.168.1.100 &lt;span class="c1"&gt;# サーバーのIPまたはホスト名&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; User my-username &lt;span class="c1"&gt;# リモートサーバーのユーザー名&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IdentityFile ~/.ssh/id_rsa &lt;span class="c1"&gt;# SSH鍵のパス（鍵認証を使用する場合）&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;&#10;&lt;li&gt;ファイルを保存して閉じます。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;💡 &lt;strong&gt;ヒント&lt;/strong&gt;: &lt;code&gt;Host&lt;/code&gt;の値（例: &lt;code&gt;my-remote-server&lt;/code&gt;）は任意の名前でOK。後で接続時にこの名前を使用します。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h3 id="3-リモートサーバーに接続"&gt;3. リモートサーバーに接続&#10;&lt;/h3&gt;&lt;ol&gt;&#10;&lt;li&gt;VSCode左下の緑色の「リモートアイコン」をクリック。&lt;/li&gt;&#10;&lt;li&gt;「Connect to Host」を選択。&lt;/li&gt;&#10;&lt;li&gt;先ほど設定したエイリアス名（例: &lt;code&gt;my-remote-server&lt;/code&gt;）を選択。&lt;/li&gt;&#10;&lt;li&gt;初回接続時に「このホストのSSHキーを信頼するか」と聞かれるので「Yes」を選択。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;リモートサーバーに接続されると、VSCodeのウィンドウが再起動し、リモート環境として動作します。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h3 id="4-リモートフォルダを開く"&gt;4. リモートフォルダを開く&#10;&lt;/h3&gt;&lt;p&gt;接続後、リモートサーバー上の作業ディレクトリを開きます。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;左側のエクスプローラーで「Open Folder」をクリック。&lt;/li&gt;&#10;&lt;li&gt;リモートサーバー上のディレクトリ（例: &lt;code&gt;/home/my-username/project&lt;/code&gt;）を選択。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;これで、リモートサーバー上のコードがVSCodeで編集可能になります！&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h3 id="5-リモート環境での開発"&gt;5. リモート環境での開発&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;リモート環境に必要な拡張機能（例: Python、Node.js関連）をインストールする際は、「Install in SSH: [Host名]」を選択してください。&lt;/li&gt;&#10;&lt;li&gt;ターミナルを開くには、&lt;code&gt;Ctrl +&lt;/code&gt;（バッククォート） ``を押します。リモートサーバーのターミナルが利用できます。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="-トラブルシューティング"&gt;🛠 トラブルシューティング&#10;&lt;/h2&gt;&lt;h3 id="q1-ssh接続エラーが発生する"&gt;Q1. SSH接続エラーが発生する&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;SSH設定ファイル（&lt;code&gt;~/.ssh/config&lt;/code&gt;）の記述を再確認。&lt;/li&gt;&#10;&lt;li&gt;ターミナルで以下を実行してSSH接続が可能か確認:&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh my-remote-server&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="q2-拡張機能がインストールされない"&gt;Q2. 拡張機能がインストールされない&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;拡張機能画面で「Install in SSH」を選択しているか確認。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="q3-権限エラーが発生"&gt;Q3. 権限エラーが発生&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;リモートサーバー上のファイル・フォルダの権限設定を確認します:&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod -R u+w /path/to/directory&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;hr&gt;&#10;&lt;p&gt;これで、リモートサーバーでの開発作業が快適になるはずです！&lt;br&gt;&#10;VSCodeと「Remote - SSH」を使って、効率的なリモート開発を楽しんでください。&lt;/p&gt;&#10;</description></item><item><title>JPGなど画像ファイルを圧縮したCBZ,ZIPファイルをPDFに変換する</title><link>https://ai.hack-le.com/zip-cbz-pdf/</link><pubDate>Wed, 25 Sep 2024 12:50:58 +0900</pubDate><guid>https://ai.hack-le.com/zip-cbz-pdf/</guid><description>&lt;p&gt;電子書籍や漫画のフォーマットとしてよく使われる&lt;code&gt;CBZ&lt;/code&gt;ファイルは、実際にはZIP形式で圧縮されたJPEG画像の集まりです。今回は、この&lt;code&gt;CBZ&lt;/code&gt;ファイルを簡単に&lt;code&gt;PDF&lt;/code&gt;に変換する方法を紹介します。&lt;/p&gt;&#10;&lt;p&gt;手順は非常にシンプルで、無料のコマンドラインツールを使って効率よく変換できます。ぜひ試してみてください。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="必要なツール"&gt;必要なツール&#10;&lt;/h2&gt;&lt;p&gt;以下のツールが必要です。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;unzip&lt;/code&gt;（通常のZIPファイル解凍に使います）&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;img2pdf&lt;/code&gt;（画像をPDFにまとめるためのツール）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;code&gt;img2pdf&lt;/code&gt;はPythonベースのツールで、簡単にインストールできます。まだインストールしていない場合、次のコマンドを使用してインストールしましょう。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install img2pdf&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;h2 id="手順"&gt;手順&#10;&lt;/h2&gt;&lt;h3 id="cbzファイルを解凍する"&gt;CBZファイルを解凍する&#10;&lt;/h3&gt;&lt;p&gt;まず、&lt;code&gt;.cbz&lt;/code&gt;ファイルを&lt;code&gt;unzip&lt;/code&gt;コマンドで解凍し、中のJPEG画像を取り出します。次のようにコマンドを実行してください。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;unzip your_file.cbz -d extracted_images&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;your_file.cbz&lt;/code&gt;は変換したいCBZファイルの名前、&lt;code&gt;extracted_images&lt;/code&gt;は画像を解凍するディレクトリです。&lt;/p&gt;&#10;&lt;h3 id="画像をpdfに変換する"&gt;画像をPDFに変換する&#10;&lt;/h3&gt;&lt;p&gt;次に、解凍されたJPEG画像を1つのPDFファイルにまとめます。&lt;code&gt;img2pdf&lt;/code&gt;コマンドを使って、指定したディレクトリ内のJPEG画像をPDF形式に変換します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;img2pdf extracted_images/*.jpg -o output.pdf&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで、&lt;code&gt;output.pdf&lt;/code&gt;という名前のPDFファイルが作成されます。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="スクリプト化"&gt;スクリプト化&#10;&lt;/h2&gt;&lt;p&gt;次のようなBashスクリプトを作成すれば、&lt;code&gt;.cbz&lt;/code&gt;ファイルをPDFに変換し、同じファイル名のPDFを出力し、途中で生成された不要なファイルを削除できます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CBZファイルを引数として受け取る&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt; filename.cbz&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ファイル名とディレクトリを分離&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;cbz_file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;basename &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$cbz_file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; .cbz&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;dirname &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$cbz_file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 一時ディレクトリを作成&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;temp_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;mktemp -d&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CBZファイルを解凍&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;unzip &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$cbz_file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; -d &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$temp_dir&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 画像ファイルをPDFに変換&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;img2pdf &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$temp_dir&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;/*.jpg -o &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$directory&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$filename&lt;/span&gt;&lt;span class="s2"&gt;.pdf&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 一時ディレクトリを削除&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm -rf &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$temp_dir&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Conversion completed: &lt;/span&gt;&lt;span class="nv"&gt;$filename&lt;/span&gt;&lt;span class="s2"&gt;.pdf&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;以上で、CBZファイルを簡単にPDFに変換できる手順を紹介しました。特別なソフトウェアは必要なく、コマンドラインだけでサクッと変換できるので、ぜひこの方法を活用してください。漫画や電子書籍をPDF化して整理したい方にぴったりの方法です。&lt;/p&gt;&#10;</description></item><item><title>一度コミットしたファイルを .gitignore に追加して追跡から外す手順</title><link>https://ai.hack-le.com/gitignore-cached/</link><pubDate>Sat, 21 Sep 2024 10:05:06 +0900</pubDate><guid>https://ai.hack-le.com/gitignore-cached/</guid><description>&lt;p&gt;プロジェクトの開発中に、一時的なファイルやビルドアーティファクトを誤って Git にコミットしてしまうことがあります。通常、これらのファイルは &lt;code&gt;.gitignore&lt;/code&gt; に追加してリポジトリに含めないようにするのが一般的ですが、既にコミットされている場合、追跡から外す必要があります。&lt;/p&gt;&#10;&lt;h2 id="手順"&gt;手順&#10;&lt;/h2&gt;&lt;h3 id="gitignore-にファイルやフォルダを追加する"&gt;&lt;code&gt;.gitignore&lt;/code&gt; にファイルやフォルダを追加する&#10;&lt;/h3&gt;&lt;p&gt;まず、追跡したくないファイルやフォルダを &lt;code&gt;.gitignore&lt;/code&gt; に追加します。たとえば、ビルドアーティファクトや一時ファイルを無視する場合は、以下のように記述します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 追跡しないファイルやフォルダを指定&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;build/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;temp/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.env&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;.gitignore&lt;/code&gt; に追加することで、今後これらのファイルやフォルダは新たに Git の追跡対象から外されますが、既にコミットされたものは追跡されたままです。&lt;/p&gt;&#10;&lt;h3 id="既に追跡されているファイルやフォルダをインデックスから削除"&gt;既に追跡されているファイルやフォルダをインデックスから削除&#10;&lt;/h3&gt;&lt;p&gt;既にコミットされているファイルやフォルダを Git の追跡から外すには、以下のコマンドを実行してインデックスから削除します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git rm -r --cached &amp;lt;ファイル名またはフォルダ名&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;&amp;lt;ファイル名またはフォルダ名&amp;gt;&lt;/code&gt; の部分には、追跡から外したいファイルやフォルダのパスを指定します。&lt;code&gt;--cached&lt;/code&gt; オプションを付けることで、ローカルのファイルは削除されず、Git の追跡からのみ外れます。&lt;/p&gt;&#10;&lt;p&gt;例として、ビルドディレクトリ &lt;code&gt;build/&lt;/code&gt; を追跡から外す場合は次のようにします。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git rm -r --cached build/&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="変更をコミット"&gt;変更をコミット&#10;&lt;/h3&gt;&lt;p&gt;インデックスから削除したファイルやフォルダの変更をコミットします。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &amp;#34;Remove build directory from tracking&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで、指定したファイルやフォルダは Git で追跡されなくなります。&lt;/p&gt;&#10;&lt;h3 id="リモートにプッシュ"&gt;リモートにプッシュ&#10;&lt;/h3&gt;&lt;p&gt;最後に、変更をリモートリポジトリにプッシュします。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git push origin &amp;lt;your-branch&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;&amp;lt;your-branch&amp;gt;&lt;/code&gt; の部分には作業中のブランチ名を指定します。&lt;/p&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;誤ってコミットしてしまった一時ファイルやビルドアーティファクトを Git の追跡から外す際は、次の手順を覚えておくと便利です。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;code&gt;.gitignore&lt;/code&gt; に無視するファイルやフォルダを追加&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git rm --cached&lt;/code&gt; コマンドでインデックスから削除&lt;/li&gt;&#10;&lt;li&gt;変更をコミットしてリモートにプッシュ&lt;/li&gt;&#10;&lt;/ol&gt;&#10;</description></item><item><title>ファイル名に数字の部分があったら、桁数を引数で指定してゼロ埋めするbashスクリプト</title><link>https://ai.hack-le.com/file-zeropadding-script/</link><pubDate>Mon, 12 Aug 2024 16:08:18 +0900</pubDate><guid>https://ai.hack-le.com/file-zeropadding-script/</guid><description>&lt;p&gt;この記事では、ファイル名に含まれる数字部分を指定した桁数でゼロ埋めするBashスクリプトを紹介し、その技術的な詳細を解説します。このスクリプトは、数字部分を柔軟に処理し、デフォルトで4桁、引数を指定することで任意の桁数でゼロ埋めすることができます。MacやLinux環境で動作し、ファイル名の管理や整理を効率的に行えます。&lt;/p&gt;&#10;&lt;h2 id="スクリプトの概要"&gt;スクリプトの概要&#10;&lt;/h2&gt;&lt;p&gt;このスクリプトは、ディレクトリ内のすべてのファイルを対象にして、ファイル名に含まれる数字部分を指定された桁数でゼロ埋めします。ゼロ埋めの桁数は、スクリプトの引数として指定することができ、引数が指定されない場合はデフォルトで4桁になります。&lt;/p&gt;&#10;&lt;h2 id="スクリプト全文"&gt;スクリプト全文&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ゼロ埋めする桁数を引数から取得、デフォルトは4桁&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;pad_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;4&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ディレクトリ内のすべてのファイルを処理する&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ファイル名を変数に格納&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;original_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;modified_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ファイル名の各部分をチェック&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -r -n1 char&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$char&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ &lt;span class="o"&gt;[&lt;/span&gt;0-9&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$number$char&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$number&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 8進数の解釈を避けるため、整数として扱う&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="m"&gt;10#&lt;/span&gt;&lt;span class="nv"&gt;$number&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="si"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; -le &lt;span class="nv"&gt;$pad_length&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;modified_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;modified_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;%0&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;pad_length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;d&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$number&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;modified_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;modified_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nv"&gt;$number&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;modified_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$modified_name$char&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;done&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$original_name&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 末尾に数字があった場合、それをゼロ埋めする&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$number&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="m"&gt;10#&lt;/span&gt;&lt;span class="nv"&gt;$number&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="si"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; -le &lt;span class="nv"&gt;$pad_length&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;modified_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;modified_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;%0&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;pad_length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;d&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$number&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;modified_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;modified_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nv"&gt;$number&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 名前が変更されていればファイル名を変更&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$original_name&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; !&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$modified_name&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mv &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$original_name&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$modified_name&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Renamed: &lt;/span&gt;&lt;span class="nv"&gt;$original_name&lt;/span&gt;&lt;span class="s2"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="nv"&gt;$modified_name&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="技術的な解説"&gt;技術的な解説&#10;&lt;/h2&gt;&lt;h3 id="引数による桁数の指定"&gt;引数による桁数の指定&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;pad_length=${1:-4}&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;この部分は、スクリプトに渡された引数を &lt;code&gt;pad_length&lt;/code&gt; という変数に代入しています。引数が指定されなかった場合には、デフォルトで4桁が使用されます。これにより、ユーザーは必要に応じて任意の桁数でゼロ埋めが可能です。&lt;/p&gt;&#10;&lt;h3 id="ファイル名の処理"&gt;ファイル名の処理&#10;&lt;/h3&gt;&lt;p&gt;スクリプトは、&lt;code&gt;for file in *; do&lt;/code&gt; ループを使って、現在のディレクトリ内にあるすべてのファイルを順番に処理します。ファイル名の各文字を1文字ずつチェックし、数字部分を検出してゼロ埋めを行います。&lt;/p&gt;&#10;&lt;h3 id="8進数の解釈を回避"&gt;8進数の解釈を回避&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;number=$((10#$number))&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;printf&lt;/code&gt; コマンドは、数字の先頭にゼロがついていると、それを8進数として解釈しようとします。このため、先頭のゼロを取り除いてから処理を行う必要があります。この行で &lt;code&gt;number&lt;/code&gt; 変数を整数に変換し、8進数の誤解釈を回避しています。&lt;/p&gt;&#10;&lt;h3 id="printf-を使ったゼロ埋め"&gt;&lt;code&gt;printf&lt;/code&gt; を使ったゼロ埋め&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;modified_name=&amp;quot;${modified_name}$(printf &amp;quot;%0${pad_length}d&amp;quot; &amp;quot;$number&amp;quot;)&amp;quot;&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;この部分で、&lt;code&gt;printf&lt;/code&gt; コマンドを使用して、指定された桁数で数字をゼロ埋めしています。&lt;code&gt;${pad_length}&lt;/code&gt; によってゼロ埋めする桁数が動的に決定されます。&lt;/p&gt;&#10;&lt;h3 id="ファイル名の変更"&gt;ファイル名の変更&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;mv &amp;quot;$original_name&amp;quot; &amp;quot;$modified_name&amp;quot;&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;最後に、元のファイル名とゼロ埋めされた新しいファイル名を比較し、異なる場合は&lt;code&gt;mv&lt;/code&gt;コマンドを使用してファイル名を変更します。これにより、ファイルが適切にリネームされ、処理が完了します。&lt;/p&gt;&#10;&lt;h2 id="使用例"&gt;使用例&#10;&lt;/h2&gt;&lt;p&gt;このスクリプトを利用する際の基本的な実行例を以下に示します。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;デフォルトで4桁ゼロ埋めを行う場合：&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./rename_files.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;&#10;&lt;li&gt;6桁でゼロ埋めを行いたい場合：&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./rename_files.sh 6&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このようにして、任意の桁数で数字部分をゼロ埋めすることができます。ファイル名に含まれる複数の数字部分にも対応しており、ファイル管理の際に役立つツールとなるでしょう。&lt;/p&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;このスクリプトは、Bashでのファイル名処理を強力かつ柔軟に行うための便利なツールです。MacやLinuxの環境でスムーズに動作し、シンプルなコマンドでファイル名の数字部分を整形することができます。ぜひ、ご自身のプロジェクトで活用してみてください。&lt;/p&gt;&#10;</description></item><item><title>ディレクトリベースで複数のGitHubアカウントを管理する方法</title><link>https://ai.hack-le.com/directory-github/</link><pubDate>Thu, 04 Jul 2024 18:56:23 +0900</pubDate><guid>https://ai.hack-le.com/directory-github/</guid><description>&lt;p&gt;この記事では、個人用と仕事用のGitHubアカウントを、プロジェクトディレクトリごとに自動的に切り替えて使用する方法を詳しく解説します。具体的には、&lt;code&gt;~/projects/personal&lt;/code&gt; ディレクトリ下のプロジェクトでは個人のGitHubアカウントを使用し、&lt;code&gt;~/projects/work&lt;/code&gt; ディレクトリ下では仕事用のアカウントを使用する状況を想定します。コマンドラインでのGit操作だけでなく、VSCodeなどのIDEでも適用されるようにします。&lt;/p&gt;&#10;&lt;h2 id="前提条件"&gt;前提条件&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;Gitの基本的な知識があること。&lt;/li&gt;&#10;&lt;li&gt;アカウントごとにSSHキーを生成しており、それぞれのGitHubアカウントに登録していること。&lt;/li&gt;&#10;&lt;li&gt;基本的なGit操作に慣れていること。&lt;/li&gt;&#10;&lt;li&gt;Git 2.13以降であること。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="git設定の基本"&gt;Git設定の基本&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;.gitconfig&lt;/code&gt;ファイルはGitの設定を管理するための中心的なファイルで、ユーザ名やメールアドレス、エイリアス、スクリプトの実行設定などを含みます。全体的なユーザー設定（グローバル設定）は通常、ユーザのホームディレクトリに位置する&lt;code&gt;.gitconfig&lt;/code&gt;ファイルに記述されます。&lt;/p&gt;&#10;&lt;h3 id="ディレクトリごとのgit設定"&gt;ディレクトリごとのGit設定&#10;&lt;/h3&gt;&lt;p&gt;Git 2.13以上では、&lt;code&gt;includeIf&lt;/code&gt;ディレクティブを使用して、特定のディレクトリに基づいてGit設定を動的に適用することができます。これを利用して、異なるプロジェクトディレクトリで異なるGitHubアカウントを使い分ける設定を行います。&lt;/p&gt;&#10;&lt;h4 id="基本的なgitconfig設定"&gt;基本的な&lt;code&gt;.gitconfig&lt;/code&gt;設定&#10;&lt;/h4&gt;&lt;p&gt;ホームディレクトリの&lt;code&gt;.gitconfig&lt;/code&gt;に以下の設定を追加します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[user]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name = default_name&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; email = default_email@example.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[includeIf &amp;#34;gitdir:~/projects/personal/&amp;#34;]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; path = ~/.gitconfig-personal&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[includeIf &amp;#34;gitdir:~/projects/work/&amp;#34;]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; path = ~/.gitconfig-work&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="各ディレクトリ用のgitconfigファイル"&gt;各ディレクトリ用の&lt;code&gt;.gitconfig&lt;/code&gt;ファイル&#10;&lt;/h4&gt;&lt;p&gt;&lt;code&gt;~/.gitconfig-personal&lt;/code&gt;ファイルには次のように記述します：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[user]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name = personal_username&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; email = personal_email@example.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[core]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sshCommand = &amp;#34;ssh -i ~/.ssh/id_rsa_personal -F /dev/null&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;~/.gitconfig-work&lt;/code&gt;ファイルには次のように記述します：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[user]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name = work_username&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; email = work_email@example.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[core]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sshCommand = &amp;#34;ssh -i ~/.ssh/id_rsa_work -F /dev/null&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;ディレクトリベースでGitHubアカウントを管理することで、複数のアカウントを効率的かつ安全に運用することが可能です。設定は初めに少し時間がかかりますが、一度設定してしまえば、その後は自動で適切なアカウントが使用されるため、非常に便利です。&lt;/p&gt;&#10;</description></item><item><title>カレントディレクトリ以下のすべてのpng,jpgをwebpに変換するシェルスクリプト</title><link>https://ai.hack-le.com/pngjpg-webp/</link><pubDate>Mon, 25 Mar 2024 16:23:39 +0900</pubDate><guid>https://ai.hack-le.com/pngjpg-webp/</guid><description>&lt;p&gt;&lt;strong&gt;この記事の目的は、シェルスクリプトでカレントディレクトリ以下にあるjpgやpngといった画像ファイルを、すべてwebpに変換する&lt;/strong&gt;ことです。サブディレクトリ内のデータも含みます。また、高速化のために並列処理をします。&lt;/p&gt;&#10;&lt;p&gt;実行環境&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Machine: M2 Pro Mac mini (2023)&lt;/li&gt;&#10;&lt;li&gt;macOS Sonoma 14.3.1&lt;/li&gt;&#10;&lt;li&gt;GNU bash 5.2.26&lt;/li&gt;&#10;&lt;li&gt;ImageMagick 7.1.1-29&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="スクリプトの提示"&gt;スクリプトの提示&#10;&lt;/h2&gt;&lt;p&gt;以下に、この自動化された並列処理を実行するためのbashスクリプトを示します。このスクリプトは、指定したディレクトリ以下の画像ファイル（PNG、JPG、JPEG）を検索し、それらをwebpフォーマットに変換後、元のファイルを削除します。変換プロセスは並列で実行されるため、作業の完了にかかる時間が大幅に短縮されます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;convert_image&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;img&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;basename &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$img&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; .&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;img&lt;/span&gt;&lt;span class="p"&gt;##*.&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;dirname &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$img&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;new_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt;.webp&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; convert &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$img&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$new_path&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$img&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; -f convert_image&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -type f &lt;span class="se"&gt;\(&lt;/span&gt; -iname &lt;span class="se"&gt;\*&lt;/span&gt;.png -o -iname &lt;span class="se"&gt;\*&lt;/span&gt;.jpg -o -iname &lt;span class="se"&gt;\*&lt;/span&gt;.jpeg &lt;span class="se"&gt;\)&lt;/span&gt; -print0 &lt;span class="p"&gt;|&lt;/span&gt; parallel -0 convert_image&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このスクリプトは、すべてのPNG、JPG、およびJPEGファイルを現在のディレクトリおよびそのサブディレクトリから検索し、それぞれをwebpフォーマットに変換した後、元のファイルを削除します。この自動化されたプロセスにより、手動で行う場合と比べて大幅な時間短縮が可能になります。&lt;/p&gt;&#10;&lt;h2 id="スクリプトの実行方法"&gt;スクリプトの実行方法&#10;&lt;/h2&gt;&lt;p&gt;このセクションでは、前述のbashスクリプトを実行するために必要な環境設定と、スクリプトの具体的な使用方法について詳しく説明します。スクリプトを効果的に活用するには、いくつかの前提条件を満たし、適切な手順で実行することが重要です。&lt;/p&gt;&#10;&lt;p&gt;前提条件は以下です。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;ImageMagickのインストール&lt;/strong&gt;: このスクリプトは&lt;code&gt;convert&lt;/code&gt;コマンドを使用して画像をwebpフォーマットに変換します。&lt;code&gt;convert&lt;/code&gt;コマンドは、ImageMagickソフトウェアスイートの一部です。ImageMagickは多くのLinuxディストリビューション、macOS、およびWindowsで利用可能です。お使いのシステムにImageMagickがインストールされていない場合は、公式の&lt;a class="link" href="https://imagemagick.org/script/download.php" target="_blank" rel="noopener"&#10; &gt;ImageMagickダウンロードページ&lt;/a&gt;からインストールすることができます。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;GNU parallelのインストール&lt;/strong&gt;: このスクリプトはGNU parallelを使用して、画像変換プロセスを並列で実行します。これにより、複数の画像を同時に処理することができ、全体の処理時間が大幅に短縮されます。GNU parallelはLinuxディストリビューションのパッケージマネージャーや&lt;a class="link" href="https://www.gnu.org/software/parallel/" target="_blank" rel="noopener"&#10; &gt;GNU parallelの公式ページ&lt;/a&gt;を通じてインストールできます。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="スクリプトの主要部分解説"&gt;スクリプトの主要部分解説&#10;&lt;/h2&gt;&lt;p&gt;このセクションでは、先に紹介したbashスクリプトの構成要素を詳しく説明し、各部分がどのように機能するかを解説します。スクリプトは大きく分けて三つの主要な処理ステップによって構成されています。画像ファイルの検索、画像の並列変換、および元の画像ファイルの削除です。&lt;/p&gt;&#10;&lt;h3 id="1-画像ファイルの検索"&gt;1. 画像ファイルの検索&#10;&lt;/h3&gt;&lt;p&gt;スクリプトは&lt;code&gt;find&lt;/code&gt;コマンドを使用して、指定したディレクトリ以下のすべてのPNG、JPG、JPEGファイルを検索します。この検索は再帰的に行われ、サブディレクトリ内のファイルも対象となります。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -type f &lt;span class="se"&gt;\(&lt;/span&gt; -iname &lt;span class="se"&gt;\*&lt;/span&gt;.png -o -iname &lt;span class="se"&gt;\*&lt;/span&gt;.jpg -o -iname &lt;span class="se"&gt;\*&lt;/span&gt;.jpeg &lt;span class="se"&gt;\)&lt;/span&gt; -print0&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;.&lt;/code&gt;は現在のディレクトリを表します。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;-type f&lt;/code&gt;はファイルタイプが「ファイル」であるものを検索対象とします。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;-iname&lt;/code&gt;は大文字小文字を区別せずに名前が一致するファイルを検索します。ここでは、&lt;code&gt;.png&lt;/code&gt;、&lt;code&gt;.jpg&lt;/code&gt;、&lt;code&gt;.jpeg&lt;/code&gt;の各拡張子を持つファイルを対象としています。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;-print0&lt;/code&gt;は検索結果をNULL文字で区切って出力します。これは&lt;code&gt;parallel&lt;/code&gt;コマンドでの処理に必要です。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="2-画像の並列変換"&gt;2. 画像の並列変換&#10;&lt;/h3&gt;&lt;p&gt;検索した画像ファイルは&lt;code&gt;parallel&lt;/code&gt;コマンドを通じて並列に処理されます。このステップでは、各画像ファイルがwebpフォーマットに変換されます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;parallel -0 convert_image&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;-0&lt;/code&gt;オプションは、入力がNULL文字で区切られていることを&lt;code&gt;parallel&lt;/code&gt;に指示します。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;convert_image&lt;/code&gt;は画像を変換するために定義された関数です。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;GNU parallelは、複数のプロセスを並列で実行するための強力なツールです。このスクリプトでは、&lt;code&gt;parallel&lt;/code&gt;コマンドを用いて、検索された各画像ファイルに対して&lt;code&gt;convert_image&lt;/code&gt;関数を同時に実行させています。これにより、画像の変換タスクがCPUの複数のコアに分散され、タスクの完了速度が向上します。&lt;/p&gt;&#10;&lt;h3 id="3-画像変換関数-convert_image"&gt;3. 画像変換関数 &lt;code&gt;convert_image&lt;/code&gt;&#10;&lt;/h3&gt;&lt;p&gt;この関数は、個々の画像ファイルをwebpフォーマットに変換し、成功したら元のファイルを削除します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;convert_image&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;img&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;basename &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$img&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; .&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;img&lt;/span&gt;&lt;span class="p"&gt;##*.&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;dirname &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$img&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;new_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt;.webp&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; convert &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$img&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$new_path&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$img&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;img=&amp;quot;$1&amp;quot;&lt;/code&gt;は関数に渡された最初の引数（ここでは画像ファイルのパス）を変数&lt;code&gt;img&lt;/code&gt;に代入します。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;basename&lt;/code&gt;と&lt;code&gt;dirname&lt;/code&gt;コマンドを使用して、ファイル名（拡張子なし）とディレクトリのパスを取得します。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;convert&lt;/code&gt;コマンドは画像をwebpフォーマットに変換します。変換が成功した場合（&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;の後）、&lt;code&gt;rm&lt;/code&gt;コマンドによって元のファイルが削除されます。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;このスクリプトによって、大量の画像ファイルを効率的にwebpフォーマットに変換するプロセスが自動化されます。並列処理の採用により、この変換作業を大幅に高速化することができます。&lt;/p&gt;&#10;&lt;h2 id="トラブルシューティング"&gt;トラブルシューティング&#10;&lt;/h2&gt;&lt;p&gt;実際にスクリプトを使用する際には、いくつかの一般的な問題に遭遇する可能性があります。このセクションでは、最も一般的な問題とその解決策をいくつか紹介します。&lt;/p&gt;&#10;&lt;h3 id="1-gnu-parallelが見つからない"&gt;1. GNU parallelが見つからない&#10;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;問題&lt;/strong&gt;: スクリプトを実行しようとすると、「parallel: command not found」というエラーメッセージが表示されます。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;解決策&lt;/strong&gt;:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;GNU parallelがインストールされているかどうかを確認してください。インストールされていない場合は、お使いのシステムのパッケージマネージャーを使用してインストールします。例えば、Ubuntuでは&lt;code&gt;sudo apt-get install parallel&lt;/code&gt;を実行します。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="2-imagemagickのconvertコマンドが機能しない"&gt;2. ImageMagickのconvertコマンドが機能しない&#10;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;問題&lt;/strong&gt;: &lt;code&gt;convert&lt;/code&gt;コマンドを実行しようとするとエラーが発生するか、期待される出力が得られない。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;解決策&lt;/strong&gt;:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;ImageMagickが正しくインストールされているかを確認してください。インストールされていない、またはバージョンが古い場合は、最新版を公式ウェブサイトからダウンロードしてインストールします。&lt;/li&gt;&#10;&lt;li&gt;特にMac OSの場合、ImageMagickの最新バージョンでは&lt;code&gt;convert&lt;/code&gt;コマンドが&lt;code&gt;magick convert&lt;/code&gt;に置き換えられている可能性があります。その場合は、スクリプト内の&lt;code&gt;convert&lt;/code&gt;コマンドを&lt;code&gt;magick convert&lt;/code&gt;に変更してください。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="3-スクリプトが特定の画像ファイルを見つけられない"&gt;3. スクリプトが特定の画像ファイルを見つけられない&#10;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;問題&lt;/strong&gt;: スクリプトを実行しても、一部の画像ファイルが処理されない。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;解決策&lt;/strong&gt;:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;find&lt;/code&gt;コマンドのパターンが正しいか確認してください。大文字小文字の違いが原因でファイルが見落とされることがあります。&lt;code&gt;-iname&lt;/code&gt;オプションは大文字小文字を区別しないため、これを使用していることを確認してください。&lt;/li&gt;&#10;&lt;li&gt;スクリプトが実行されているディレクトリと、処理したい画像ファイルが格納されているディレクトリが一致しているかを確認してください。必要に応じて、&lt;code&gt;find&lt;/code&gt;コマンドの検索パスを調整します。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="参考資料"&gt;参考資料&#10;&lt;/h2&gt;&lt;p&gt;この記事では、大量の画像ファイルを効率的にwebp形式に変換し、そのプロセスを並列で実行するbashスクリプトの作成と使用について詳しく説明しました。このスクリプトを使用することで、画像処理タスクの時間を大幅に短縮し、ウェブサイトのパフォーマンスを向上させることができます。また、GNU parallelとImageMagickを活用することで、マルチコアプロセッサの能力を最大限に引き出し、作業の効率を向上させる方法も紹介しました。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://www.gnu.org/software/parallel/" target="_blank" rel="noopener"&#10; &gt;GNU Parallel Official Documentation&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://imagemagick.org/index.php" target="_blank" rel="noopener"&#10; &gt;ImageMagick Official Documentation&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>カレントディレクトリの.rarファイルを展開する(Bash, Fish)</title><link>https://ai.hack-le.com/%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%88%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%81%AE-rar%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%B1%95%E9%96%8B%E3%81%99%E3%82%8Bbash-fish/</link><pubDate>Wed, 03 Jan 2024 09:21:21 +0900</pubDate><guid>https://ai.hack-le.com/%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%88%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%81%AE-rar%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%B1%95%E9%96%8B%E3%81%99%E3%82%8Bbash-fish/</guid><description>&lt;p&gt;&lt;code&gt;.rar&lt;/code&gt; ファイルを Bash や Fish シェルで展開するためには、&lt;code&gt;unrar&lt;/code&gt; または &lt;code&gt;rar&lt;/code&gt; コマンドを使用します。これらのコマンドは &lt;code&gt;.rar&lt;/code&gt; 形式のファイルを処理するための標準的なツールです。まず、これらのコマンドがシステムにインストールされているか確認し、インストールされていなければ適切な手順でインストールしてください。&lt;/p&gt;&#10;&lt;h3 id="bash-での-rar-ファイルの展開"&gt;Bash での .rar ファイルの展開&#10;&lt;/h3&gt;&lt;p&gt;Bash シェルを使用して &lt;code&gt;.rar&lt;/code&gt; ファイルを展開するには、以下のコマンドを実行します：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;for file in *.rar; do unrar x &amp;#34;$file&amp;#34;; done&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドは、カレントディレクトリに存在する全ての &lt;code&gt;.rar&lt;/code&gt; ファイルを検索し、&lt;code&gt;unrar x&lt;/code&gt; コマンドを使ってそれぞれを展開します。&lt;/p&gt;&#10;&lt;h3 id="fish-での-rar-ファイルの展開"&gt;Fish での .rar ファイルの展開&#10;&lt;/h3&gt;&lt;p&gt;Fish シェルで &lt;code&gt;.rar&lt;/code&gt; ファイルを展開する場合、コマンドは少し異なりますが、基本的なプロセスは同じです。以下が Fish でのコマンドです：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;for file in *.rar; unrar x $file; end&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドも、カレントディレクトリの全ての &lt;code&gt;.rar&lt;/code&gt; ファイルに対して &lt;code&gt;unrar&lt;/code&gt; コマンドを実行します。&lt;/p&gt;&#10;&lt;h3 id="注意点"&gt;注意点&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;unrar&lt;/code&gt; コマンドがシステムにインストールされている必要があります。Linux や Unix 系の OS では、パッケージマネージャを通じてインストールできます。例えば、Debian 系のディストリビューションでは &lt;code&gt;sudo apt-get install unrar&lt;/code&gt; コマンドでインストールできます。&lt;/li&gt;&#10;&lt;li&gt;Macの場合は &lt;a class="link" href="https://qiita.com/wm-ytakano/items/ec03961978f5578906a2" target="_blank" rel="noopener"&#10; &gt;MacでRARファイルをコマンドラインで解凍する(unrar) #Mac - Qiita&lt;/a&gt; より &lt;code&gt;$ brew install carlocab/personal/unrar&lt;/code&gt;でインストールできます。&lt;/li&gt;&#10;&lt;li&gt;展開したいファイルが保存されているディレクトリに移動してからコマンドを実行してください。&lt;/li&gt;&#10;&lt;li&gt;ファイル名にスペースや特殊文字が含まれている場合は、ファイル名をダブルクォートで囲むことで、正しく処理されるようにしてください。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>カレントディレクトリの.lzhファイルをBashとFishで展開する方法</title><link>https://ai.hack-le.com/lzh-bash-fish/</link><pubDate>Wed, 03 Jan 2024 09:01:58 +0900</pubDate><guid>https://ai.hack-le.com/lzh-bash-fish/</guid><description>&lt;p&gt;コンピュータを使った作業では、様々なファイルを扱いますが、特にアーカイブファイルはその中でも重要な役割を果たしています。アーカイブファイルには多くの種類がありますが、今回は&lt;code&gt;.lzh&lt;/code&gt;形式のファイルに注目します。&lt;code&gt;.lzh&lt;/code&gt;はかつて日本で広く使われていた圧縮形式で、今でも歴史的なデータや特定のコンテンツを扱う際に見かけることがあります。&lt;/p&gt;&#10;&lt;p&gt;このブログ記事では、&lt;code&gt;.lzh&lt;/code&gt;ファイルを効率的に展開する方法を、BashとFishという二つの異なるシェルを使って紹介します。BashはLinuxやUnix系のオペレーティングシステムで最も一般的に使われるシェルで、その強力なスクリプト機能は多くのユーザーに愛されています。一方で、Fishはより最近のシェルで、そのユーザーフレンドリーな設計と直感的な構文が特徴です。&lt;/p&gt;&#10;&lt;h2 id="bashでのlzhファイルの展開"&gt;Bashでの.lzhファイルの展開&#10;&lt;/h2&gt;&lt;p&gt;Bashシェルは、LinuxやUnix系のオペレーティングシステムで広く採用されているコマンドラインインターフェースです。その強力なスクリプティング機能と柔軟性により、多くの開発者やシステム管理者にとって欠かせないツールとなっています。ここでは、Bashを使用して&lt;code&gt;.lzh&lt;/code&gt;ファイルを効率的に展開する方法を紹介します。&lt;/p&gt;&#10;&lt;p&gt;まず、&lt;code&gt;.lzh&lt;/code&gt;ファイルの展開には&lt;code&gt;lha&lt;/code&gt;コマンドが必要です。このコマンドは多くのLinuxディストリビューションやUnix系OSで利用可能ですが、インストールされていない場合は、パッケージマネージャを通じてインストールする必要があります。例えば、Debian系のLinuxディストリビューションでは、次のコマンドで&lt;code&gt;lha&lt;/code&gt;をインストールできます：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt-get install lha&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;インストールが完了したら、カレントディレクトリにあるすべての&lt;code&gt;.lzh&lt;/code&gt;ファイルを展開するためのコマンドを実行します。以下がそのコマンドです：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *.lzh&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; lha x &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドは、カレントディレクトリに存在するすべての&lt;code&gt;.lzh&lt;/code&gt;ファイルに対して、ループを用いて一つずつ&lt;code&gt;lha x&lt;/code&gt;コマンドを実行します。&lt;code&gt;for&lt;/code&gt;ループの中で、&lt;code&gt;*.lzh&lt;/code&gt;はカレントディレクトリ内の全ての&lt;code&gt;.lzh&lt;/code&gt;ファイルにマッチします。各ファイル名は&lt;code&gt;file&lt;/code&gt;変数に格納され、&lt;code&gt;lha x &amp;quot;$file&amp;quot;&lt;/code&gt;コマンドによってそれぞれのファイルが展開されます。ダブルクォーテーションは、ファイル名にスペースや特殊文字が含まれている場合に備えて、ファイル名を正しく処理するために使用します。&lt;/p&gt;&#10;&lt;h2 id="fishでのlzhファイルの展開"&gt;Fishでの.lzhファイルの展開&#10;&lt;/h2&gt;&lt;p&gt;Fishシェルは、使いやすさと直感的な機能を重視した近代的なコマンドラインシェルです。Bashと比較して、より洗練されたユーザーインターフェースとシンプルな構文を提供しています。ここでは、Fishを使用して&lt;code&gt;.lzh&lt;/code&gt;ファイルを効率的に展開する方法を紹介します。&lt;/p&gt;&#10;&lt;p&gt;Bashと同様に、Fishでの展開にも&lt;code&gt;lha&lt;/code&gt;コマンドが必要です。&lt;code&gt;lha&lt;/code&gt;がまだインストールされていない場合は、システムのパッケージマネージャを使ってインストールしてください。インストールが完了したら、以下のコマンドを実行して、カレントディレクトリにある全ての&lt;code&gt;.lzh&lt;/code&gt;ファイルを展開します：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *.lzh&lt;span class="p"&gt;;&lt;/span&gt; lha x &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; end&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドは、カレントディレクトリ内の全ての&lt;code&gt;.lzh&lt;/code&gt;ファイルに対して&lt;code&gt;lha&lt;/code&gt;コマンドを使用します。&lt;code&gt;for&lt;/code&gt;ループは、指定されたパターンにマッチする各ファイルに対してコマンドを実行します。ここでの&lt;code&gt;*.lzh&lt;/code&gt;は、カレントディレクトリの全ての&lt;code&gt;.lzh&lt;/code&gt;ファイルを指します。&lt;code&gt;lha x $file&lt;/code&gt;コマンドはそれぞれのファイルを展開し、&lt;code&gt;end&lt;/code&gt;キーワードでループが終了します。&lt;/p&gt;&#10;&lt;p&gt;Fishシェルの特徴の一つは、その構文の簡潔さです。Bashに比べてコマンドが短く、読みやすいため、シェルスクリプティングの初心者にも理解しやすいかもしれません。また、Fishには、コマンドの自動補完やシンタックスハイライトなどの便利な機能が標準で備わっており、日々の作業をより効率的にします。&lt;/p&gt;&#10;&lt;h2 id="注意点"&gt;注意点&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;.lzh&lt;/code&gt; ファイルを Bash や Fish で展開する際には、いくつかの重要な注意点があります。これらを理解し、適切に対処することで、ファイルの展開をスムーズかつ安全に行うことができます。&lt;/p&gt;&#10;&lt;h3 id="lha-コマンドのインストールと確認"&gt;&lt;code&gt;lha&lt;/code&gt; コマンドのインストールと確認&#10;&lt;/h3&gt;&lt;p&gt;最初に、&lt;code&gt;.lzh&lt;/code&gt; ファイルを扱うためには &lt;code&gt;lha&lt;/code&gt; コマンドが必須です。このコマンドはすべてのシステムに標準でインストールされているわけではありません。自分のシステムに &lt;code&gt;lha&lt;/code&gt; がインストールされているかを確認し、なければ適切なパッケージマネージャ（例えば、Linux の場合は &lt;code&gt;apt&lt;/code&gt; や &lt;code&gt;yum&lt;/code&gt;）を使用してインストールしてください。&lt;/p&gt;&#10;&lt;h3 id="ディレクトリの確認"&gt;ディレクトリの確認&#10;&lt;/h3&gt;&lt;p&gt;コマンドを実行する前に、カレントディレクトリが正しいかを確認することが大切です。&lt;code&gt;pwd&lt;/code&gt; コマンドを使用して現在のディレクトリを確認し、必要に応じて &lt;code&gt;cd&lt;/code&gt; コマンドで移動してください。これは、意図しないディレクトリのファイルを誤って操作することを防ぐためです。&lt;/p&gt;&#10;&lt;h3 id="ファイルのバックアップ"&gt;ファイルのバックアップ&#10;&lt;/h3&gt;&lt;p&gt;特に大切なデータを扱う場合、コマンドを実行する前にファイルのバックアップを取ることを強くお勧めします。これにより、万が一の事態が発生した場合でもデータを保護することができます。&lt;/p&gt;&#10;&lt;h3 id="ファイル名の特殊文字"&gt;ファイル名の特殊文字&#10;&lt;/h3&gt;&lt;p&gt;ファイル名にスペースや特殊文字が含まれている場合、これらを適切に処理するためにはファイル名をダブルクォートで囲むことが重要です。これは、シェルがファイル名を正しく解釈するために必要です。&lt;/p&gt;&#10;&lt;p&gt;これらの注意点を頭に入れておくことで、&lt;code&gt;.lzh&lt;/code&gt; ファイルの展開を安全かつ効率的に行うことができます。次のセクションでは、今回学んだ内容をまとめ、日常的なタスクの自動化の観点からこれらのコマンドの利用価値を評価します。&lt;/p&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;この記事では、BashおよびFishシェルを用いてカレントディレクトリにある全ての&lt;code&gt;.lzh&lt;/code&gt;ファイルを効率的に展開する方法について学びました。Bashはその強力なスクリプティング能力で広く利用されており、Fishはユーザーフレンドリーな構文と使い勝手の良さで注目されています。どちらのシェルも、&lt;code&gt;.lzh&lt;/code&gt;ファイルのような特定のファイルタイプを扱う際に、効率的で強力なツールです。&lt;/p&gt;&#10;&lt;h3 id="bashとfishの比較"&gt;BashとFishの比較&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Bash&lt;/strong&gt;: 従来からのLinuxユーザーにとって馴染み深い。スクリプティングにおける複雑なタスクを処理するのに適しており、広範囲にわたる機能を提供します。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Fish&lt;/strong&gt;: シンプルで直感的な構文を持つ新しいシェル。自動補完やシンタックスハイライトなどの便利な機能が標準で備わっており、シェルスクリプティング初心者にも扱いやすいです。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="自動化と効率化"&gt;自動化と効率化&#10;&lt;/h3&gt;&lt;p&gt;このようなシェルコマンドを使うことで、日常的に発生する繰り返しのタスクを自動化し、作業効率を大幅に向上させることが可能です。特に多くのアーカイブファイルを扱う場合、これらのコマンドを使うことで、手作業による時間の浪費を避け、より重要なタスクに集中することができます。&lt;/p&gt;&#10;&lt;h3 id="結論"&gt;結論&#10;&lt;/h3&gt;&lt;p&gt;BashとFishを使った&lt;code&gt;.lzh&lt;/code&gt;ファイルの展開方法は、日々の作業をスムーズに進めるための有効な手段です。シェルスクリプティングは、単なるコマンドライン操作以上の可能性を秘めており、これを習得することは、あらゆるIT専門家にとって価値のあるスキルです。&lt;/p&gt;&#10;&lt;p&gt;この記事が、BashとFishの使い方を理解し、より効率的なワークフローを構築する一助となれば幸いです。&lt;/p&gt;&#10;</description></item><item><title>direnvを活用したAWSアカウントの自動切り替え方法</title><link>https://ai.hack-le.com/direnv-aws/</link><pubDate>Sun, 10 Dec 2023 00:39:39 +0900</pubDate><guid>https://ai.hack-le.com/direnv-aws/</guid><description>&lt;p&gt;クラウドリソースを頻繁に使用する場合、異なるプロジェクトやクライアントごとに異なるAWSアカウントを切り替える必要があることは珍しくありません。この記事では、開発環境におけるAWSアカウントの自動切り替えを実現するために&lt;code&gt;direnv&lt;/code&gt;というツールの使用方法に焦点を当てます。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;direnv&lt;/code&gt;は、シェル環境においてディレクトリごとに環境変数を自動で切り替えることができる非常に便利なツールです。これにより、プロジェクトや作業環境に応じて、AWSプロファイルや他の環境設定を簡単に切り替えることが可能になります。この記事では、&lt;code&gt;direnv&lt;/code&gt;の基本的なインストール方法から、AWSアカウントの切り替え設定までをステップバイステップで説明していきます。&lt;/p&gt;&#10;&lt;h2 id="direnvのインストールと設定"&gt;direnvのインストールと設定&#10;&lt;/h2&gt;&lt;p&gt;開発環境のカスタマイズにおいて、&lt;code&gt;direnv&lt;/code&gt;は非常に重要なツールの一つです。&lt;code&gt;direnv&lt;/code&gt;を使用すると、異なるディレクトリに移動した際に自動的に環境変数を切り替えることができ、特に複数のAWSアカウントを使い分ける際に大いに役立ちます。ここでは、&lt;code&gt;direnv&lt;/code&gt;のインストールと基本的な設定方法について説明します。&lt;/p&gt;&#10;&lt;h3 id="direnvのインストール"&gt;direnvのインストール&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;direnv&lt;/code&gt;は多くのUnix系オペレーティングシステムで利用可能です。以下は、主要なOSにおける&lt;code&gt;direnv&lt;/code&gt;のインストール方法です：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;macOS&lt;/strong&gt;: Homebrewを使用して簡単にインストールできます。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;brew install direnv&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Ubuntu/Debian&lt;/strong&gt;: aptパッケージマネージャを利用します。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt-get install direnv&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Fedora&lt;/strong&gt;: dnfを使用してインストールします。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo dnf install direnv&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="シェルにdirenvをフックする"&gt;シェルにdirenvをフックする&#10;&lt;/h3&gt;&lt;p&gt;インストール後、&lt;code&gt;direnv&lt;/code&gt;を使用するためにはシェルにフックする必要があります。これは、使用しているシェルの設定ファイルに特定の行を追加することで行います。以下は、いくつかの一般的なシェルの設定方法です：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Bash (&lt;code&gt;.bashrc&lt;/code&gt; or &lt;code&gt;.bash_profile&lt;/code&gt;)&lt;/strong&gt; :&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;direnv hook bash&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Zsh (&lt;code&gt;.zshrc&lt;/code&gt;)&lt;/strong&gt; :&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;direnv hook zsh&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Fish (&lt;code&gt;.config/fish/config.fish&lt;/code&gt;)&lt;/strong&gt; :&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;direnv hook fish&lt;span class="o"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これらの設定を適用した後、シェルを再起動するか、新しいターミナルウィンドウを開いて設定を有効にします。&lt;/p&gt;&#10;&lt;h3 id="基本的な使用法"&gt;基本的な使用法&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;direnv&lt;/code&gt;を使うための最初のステップは、環境変数や設定を含む&lt;code&gt;.envrc&lt;/code&gt;ファイルを作成することです。このファイルは、特定のディレクトリに配置され、&lt;code&gt;direnv&lt;/code&gt;によって自動的に読み込まれます。&lt;code&gt;.envrc&lt;/code&gt;ファイルには、AWSプロファイルの設定や他の必要な環境変数を指定できます。&lt;/p&gt;&#10;&lt;p&gt;セキュリティ上の理由から、新しい&lt;code&gt;.envrc&lt;/code&gt;ファイルは&lt;code&gt;direnv&lt;/code&gt;によってデフォルトで無視されます。ファイルを承認するためには、次のコマンドを使用します：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;direnv allow .&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドは、&lt;code&gt;.envrc&lt;/code&gt;ファイルが安全であることを&lt;code&gt;direnv&lt;/code&gt;に伝え、そのディレクトリでの変更を有効にします。&lt;/p&gt;&#10;&lt;h2 id="direnvを使用したawsアカウントの実践例とトラブルシューティング"&gt;direnvを使用したAWSアカウントの実践例とトラブルシューティング&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;direnv&lt;/code&gt;を活用することで、AWSアカウントの切り替えをスムーズに行うことができます。このセクションでは、実際の使用例と一般的な問題の解決方法について説明します。&lt;/p&gt;&#10;&lt;h3 id="実際の使用例"&gt;実際の使用例&#10;&lt;/h3&gt;&lt;p&gt;想定するシナリオは、異なるAWSアカウントを使用する複数のプロジェクトに取り組んでいる状況です。それぞれのプロジェクトディレクトリに&lt;code&gt;.envrc&lt;/code&gt;ファイルを作成し、適切なAWSプロファイル名を設定します。&lt;/p&gt;&#10;&lt;p&gt;例えば、プロジェクトAとプロジェクトBがあり、それぞれ異なるAWSアカウントを使用するとします。プロジェクトAのディレクトリの&lt;code&gt;.envrc&lt;/code&gt;には以下のように書きます：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;AWS_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;projectA-profile&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;同様に、プロジェクトBの&lt;code&gt;.envrc&lt;/code&gt;には：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;AWS_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;projectB-profile&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これにより、各プロジェクトディレクトリに移動するだけで、&lt;code&gt;direnv&lt;/code&gt;が自動的にAWSプロファイルを適切なものに切り替えます。&lt;/p&gt;&#10;&lt;h3 id="トラブルシューティングのヒント"&gt;トラブルシューティングのヒント&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;問題：&lt;code&gt;.envrc&lt;/code&gt;が読み込まれない&lt;/strong&gt;&lt;/li&gt;&#10;&lt;li&gt;解決策：&lt;code&gt;direnv allow&lt;/code&gt;コマンドを使用して、&lt;code&gt;.envrc&lt;/code&gt;ファイルを承認します。また、シェルの設定ファイル（例：&lt;code&gt;.bashrc&lt;/code&gt;、&lt;code&gt;.zshrc&lt;/code&gt;、&lt;code&gt;.config/fish/config.fish&lt;/code&gt;）で&lt;code&gt;direnv&lt;/code&gt;が正しくフックされていることを確認してください。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;問題：AWSプロファイルが切り替わらない&lt;/strong&gt;&lt;/li&gt;&#10;&lt;li&gt;解決策：&lt;code&gt;AWS_PROFILE&lt;/code&gt;変数が正しく設定されているか確認します。また、AWS CLIがインストールされていること、および&lt;code&gt;~/.aws/credentials&lt;/code&gt;と&lt;code&gt;~/.aws/config&lt;/code&gt;に正しい認証情報が設定されていることを確認してください。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;問題：セキュリティ上の懸念&lt;/strong&gt;&lt;/li&gt;&#10;&lt;li&gt;解決策：&lt;code&gt;.envrc&lt;/code&gt;ファイルに機密情報（例：アクセスキー、シークレットキー）を直接書かないようにします。代わりに、プロファイル名のみを使用し、認証情報は&lt;code&gt;~/.aws/credentials&lt;/code&gt;に安全に保存します。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;direnv&lt;/code&gt;を使用したAWSプロファイルの自動切り替えの方法について詳しく説明しました。この手法は、複数のAWSアカウントを扱う際の生産性を高め、エラーの可能性を減らすのに役立ちます。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;主なポイントの再確認&lt;/strong&gt;:&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;direnv&lt;/code&gt;をインストールし、シェルにフックする。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;.envrc&lt;/code&gt;ファイルを使用して、ディレクトリごとに異なるAWSプロファイルを設定する。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;direnv allow&lt;/code&gt;を実行して、新しい&lt;code&gt;.envrc&lt;/code&gt;ファイルを承認する。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;応用例&lt;/strong&gt;: この手法はAWSプロファイルに限らず、他の環境変数や設定（例えば、データベース接続設定やAPIキー）の管理にも応用できます。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;セキュリティ上の注意&lt;/strong&gt;: &lt;code&gt;.envrc&lt;/code&gt;ファイルに機密情報を直接記述することは避け、安全な方法で認証情報を管理することが重要です。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;参考記事&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;direnv公式ドキュメント&lt;/strong&gt;: &lt;a class="link" href="https://direnv.net/" target="_blank" rel="noopener"&#10; &gt;direnv公式ウェブサイト&lt;/a&gt;には、インストール方法、使用方法、さまざまな設定オプションに関する詳細情報があります。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;AWS CLI公式ドキュメント&lt;/strong&gt;: AWS CLIの使用方法に関する詳細情報は、&lt;a class="link" href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html" target="_blank" rel="noopener"&#10; &gt;AWS公式ドキュメント&lt;/a&gt;で提供されています。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;関連ブログ記事やフォーラム&lt;/strong&gt;: コミュニティの経験やベストプラクティスを共有する多くのブログ記事やフォーラムが存在します。これらは、具体的なシナリオや高度な使用例を理解するのに役立つかもしれません。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>Macで自動化する：launchdを使ってスクリプトを起動時に実行する方法</title><link>https://ai.hack-le.com/mac-launchd/</link><pubDate>Sun, 26 Nov 2023 21:30:13 +0900</pubDate><guid>https://ai.hack-le.com/mac-launchd/</guid><description>&lt;h2 id="導入"&gt;導入&#10;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Mac OSでは、&lt;code&gt;launchd&lt;/code&gt;という強力なシステムが組み込まれています&lt;/strong&gt;。これは、さまざまなタスクを自動化するためのツールで、特にシステムの起動時や特定の条件下でプログラムやスクリプトを自動的に実行するのに適しています。&lt;code&gt;launchd&lt;/code&gt;はMacのバックグラウンドで動作し、ユーザーが意識することなく様々なプロセスを管理します。&lt;/p&gt;&#10;&lt;p&gt;この記事では、&lt;code&gt;launchd&lt;/code&gt;を使用して、Macが起動するたびに特定のスクリプトを自動的に実行する方法について詳しく説明します。&lt;/p&gt;&#10;&lt;p&gt;定期実行はこちら&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://ai.hack-le.com/macos-launchd-schedule/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;macOSのlaunchdでスクリプトを定期実行するplistのメモ&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/macos-launchd-schedule/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://ai.hack-le.com/images/uploads/2024/09/macos-launchd-schedule.webp" alt="macOSのlaunchdでスクリプトを定期実行するplistのメモ" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;h2 id="スクリプトの準備"&gt;スクリプトの準備&#10;&lt;/h2&gt;&lt;p&gt;自動化の旅を始める前に、まずは実行したいスクリプトを用意する必要があります。このステップでは、単純なシェルスクリプトを作成し、それをMacの起動時に実行する方法に焦点を当てます。シェルスクリプトは、簡単で理解しやすいので、自動化の基本を学ぶのに最適です。&lt;/p&gt;&#10;&lt;p&gt;以下は、非常に基本的なシェルスクリプトの例です。このスクリプトは、「Hello, World!」というメッセージをログファイルに書き込みます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt; &amp;gt; /path/to/your/logfile.log&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このスクリプトをテキストエディタで作成し、「myscript.sh」という名前で保存します。保存場所は、例えばホームディレクトリ内の&lt;code&gt;Scripts&lt;/code&gt;フォルダなど、容易にアクセスできる場所が適しています。&lt;/p&gt;&#10;&lt;p&gt;作成したスクリプトは、実行可能でなければなりません。これを行うには、ターミナルで次のコマンドを使用します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod +x ~/Scripts/myscript.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドにより、&lt;code&gt;myscript.sh&lt;/code&gt;に実行権限が付与されます。これでスクリプトは&lt;code&gt;launchd&lt;/code&gt;によって起動時に実行される準備が整いました。&lt;/p&gt;&#10;&lt;h2 id="plistファイルの作成と設定"&gt;.plistファイルの作成と設定&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;launchd&lt;/code&gt;を使用する際の重要な要素が&lt;code&gt;.plist&lt;/code&gt;（プロパティリスト）ファイルです。このXML形式のファイルは、&lt;code&gt;launchd&lt;/code&gt;に対して、どのスクリプトをいつ実行するか、そしてどのように実行するかを指示します。正しく設定された.plistファイルは、スクリプトを自動的に、そして安全に実行するための鍵となります。&lt;/p&gt;&#10;&lt;p&gt;ここでは、先に作成した&lt;code&gt;myscript.sh&lt;/code&gt;を起動時に実行するための.plistファイルの例を示します。以下のコードをテキストエディタで作成し、適切な名前（例：&lt;code&gt;com.yourusername.myscript.plist&lt;/code&gt;）で保存します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;?xml &lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;?&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;!DOCTYPE plist PUBLIC &lt;span class="s2"&gt;&amp;#34;-//Apple//DTD PLIST 1.0//EN&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;#34;&lt;/span&gt;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;plist &lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;dict&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;key&amp;gt;Label&amp;lt;/key&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;string&amp;gt;com.yourusername.myscript&amp;lt;/string&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;key&amp;gt;ProgramArguments&amp;lt;/key&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;array&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;string&amp;gt;/Users/yourusername/Scripts/myscript.sh&amp;lt;/string&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;/array&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;key&amp;gt;RunAtLoad&amp;lt;/key&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;true/&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/dict&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/plist&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このファイルでは、&lt;code&gt;Label&lt;/code&gt;はユニークな識別子を提供し、&lt;code&gt;ProgramArguments&lt;/code&gt;は実行するスクリプトのパスを指定します。&lt;code&gt;RunAtLoad&lt;/code&gt;が&lt;code&gt;true&lt;/code&gt;に設定されていると、Macが起動するたびにスクリプトが実行されます。&lt;/p&gt;&#10;&lt;p&gt;作成した.plistファイルを&lt;code&gt;~/Library/LaunchAgents/&lt;/code&gt;ディレクトリに保存します。この場所にファイルを置くことで、ユーザーがログインした際に自動的に&lt;code&gt;launchd&lt;/code&gt;によって読み込まれ、スクリプトが実行されるようになります。&lt;/p&gt;&#10;&lt;h2 id="plistファイルの作成と設定引数を含むスクリプトの場合"&gt;.plistファイルの作成と設定（引数を含むスクリプトの場合）&#10;&lt;/h2&gt;&lt;p&gt;スクリプトが引数を必要とする場合、それらの引数を.plistファイルに正しく組み込むことが重要です。例として、引数を受け取りログファイルに出力するシンプルなスクリプトを考えてみましょう。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Passed argument: &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &amp;gt; /path/to/your/logfile.log&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このスクリプトは引数&lt;code&gt;$1&lt;/code&gt;を取り、それをログファイルに出力します。&lt;/p&gt;&#10;&lt;p&gt;引数を含むスクリプトを自動実行するための.plistファイルは、以下のようになります。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;?xml &lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;?&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;!DOCTYPE plist PUBLIC &lt;span class="s2"&gt;&amp;#34;-//Apple//DTD PLIST 1.0//EN&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;#34;&lt;/span&gt;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;plist &lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;dict&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;key&amp;gt;Label&amp;lt;/key&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;string&amp;gt;com.yourusername.myscriptwithargs&amp;lt;/string&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;key&amp;gt;ProgramArguments&amp;lt;/key&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;array&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;string&amp;gt;/Users/yourusername/Scripts/myscript.sh&amp;lt;/string&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;string&amp;gt;Argument1&amp;lt;/string&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;/array&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;key&amp;gt;RunAtLoad&amp;lt;/key&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;true/&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/dict&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/plist&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この例では、&lt;code&gt;ProgramArguments&lt;/code&gt;キーの配列に、スクリプトのパスと引数&lt;code&gt;Argument1&lt;/code&gt;が含まれています。この設定により、スクリプトは指定した引数を持って起動時に実行されます。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;引数が正しくスクリプトに渡されることを確認するため、事前に手動でスクリプトをテストしてください。&lt;/li&gt;&#10;&lt;li&gt;引数の値が変わる場合は、その都度.plistファイルを更新し、再度&lt;code&gt;launchctl&lt;/code&gt;を使って登録する必要があります。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;このセクションでは、引数を含むスクリプトの自動実行に必要な.plistファイルの作成方法を示しました。次のセクションでは、これらの.plistファイルを実際に&lt;code&gt;launchd&lt;/code&gt;に登録し、自動実行を設定する手順について詳しく解説します。&lt;/p&gt;&#10;&lt;h2 id="launchdにスクリプトを登録する"&gt;&lt;code&gt;launchd&lt;/code&gt;にスクリプトを登録する&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;.plist&lt;/code&gt;ファイルを作成し、適切なディレクトリに配置した後、次のステップは、このファイルを&lt;code&gt;launchd&lt;/code&gt;に登録することです。これには&lt;code&gt;launchctl&lt;/code&gt;コマンドが使用されます。以下のコマンドは、新しく作成した.plistファイルを&lt;code&gt;launchd&lt;/code&gt;に登録する例です。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;launchctl load ~/Library/LaunchAgents/com.yourusername.myscript.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドは、&lt;code&gt;~/Library/LaunchAgents/&lt;/code&gt;にある&lt;code&gt;com.yourusername.myscript.plist&lt;/code&gt;という.plistファイルを&lt;code&gt;launchd&lt;/code&gt;に登録します。これにより、指定された条件（この場合はMacの起動時）にスクリプトが自動的に実行されます。&lt;/p&gt;&#10;&lt;p&gt;登録が正常に完了したかを確認するには、以下のコマンドを実行します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;launchctl list &lt;span class="p"&gt;|&lt;/span&gt; grep com.yourusername.myscript&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドは、登録されたジョブのリストから、指定した識別子&lt;code&gt;com.yourusername.myscript&lt;/code&gt;を検索します。出力結果にこの識別子が表示されれば、登録が成功していることを意味します。&lt;/p&gt;&#10;&lt;p&gt;何らかの理由で.plistファイルの登録を解除したい場合は、以下のコマンドを使用します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;launchctl unload ~/Library/LaunchAgents/com.yourusername.myscript.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドは、&lt;code&gt;com.yourusername.myscript.plist&lt;/code&gt;ファイルの登録を解除し、以降のMacの起動時にはスクリプトが実行されなくなります。&lt;/p&gt;&#10;&lt;p&gt;以下は注意点です。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;launchctl load&lt;/code&gt;コマンドは、Macが起動するたびに自動的にスクリプトを実行するように設定します。&lt;/li&gt;&#10;&lt;li&gt;登録を解除する際は、同じ.plistファイルを指定する必要があります。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;この記事では、Macの&lt;code&gt;launchd&lt;/code&gt;システムを利用して、特定のスクリプトを起動時に自動的に実行する方法について詳しく説明しました。スクリプトの準備から、.plistファイルの作成、そして&lt;code&gt;launchd&lt;/code&gt;による登録までの全ステップをカバーしました。また、引数を含むスクリプトの扱い方についても触れました。&lt;/p&gt;&#10;</description></item><item><title>pre-commitでGitのコミットメッセージのプレフィックスをチェックする</title><link>https://ai.hack-le.com/pre-commit-git/</link><pubDate>Wed, 15 Nov 2023 17:11:39 +0900</pubDate><guid>https://ai.hack-le.com/pre-commit-git/</guid><description>&lt;h2 id="はじめに"&gt;はじめに&#10;&lt;/h2&gt;&lt;p&gt;現代のソフトウェア開発では、コードの品質を維持することが非常に重要です。そのためには、バージョン管理システムであるGitを効果的に活用し、特にコミットプロセスを最適化する必要があります。このブログ記事では、&lt;code&gt;pre-commit&lt;/code&gt;を使用してコミットメッセージにプレフィックスを確認する方法について解説します。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;pre-commit&lt;/code&gt;は、Gitのコミット前に自動的に実行されるフックを設定するためのツールです。これにより、コードのスタイルチェック、テストの実行、その他の重要な検証が可能となります。特に、コミットメッセージに適切なプレフィックス（例えば&lt;code&gt;feat&lt;/code&gt;、&lt;code&gt;fix&lt;/code&gt;、&lt;code&gt;docs&lt;/code&gt;など）が含まれているかどうかを自動的に確認することは、プロジェクトの整理と追跡を容易にし、チームメンバー間のコミュニケーションを明確にします。&lt;/p&gt;&#10;&lt;p&gt;この記事では、&lt;code&gt;pre-commit&lt;/code&gt;の基本的なセットアップからカスタムスクリプトの作成、そして実際の統合に至るまでのプロセスを段階的に説明します。&lt;/p&gt;&#10;&lt;h2 id="コミットメッセージのプレフィックスの重要性"&gt;コミットメッセージのプレフィックスの重要性&#10;&lt;/h2&gt;&lt;h3 id="コミットメッセージの役割"&gt;コミットメッセージの役割&#10;&lt;/h3&gt;&lt;p&gt;コミットメッセージは、ソフトウェア開発におけるコミュニケーションの基本的な要素です。これらのメッセージは、変更内容を要約し、他の開発者や将来の自分自身がコードの変更点を理解しやすくするために使われます。良いコミットメッセージは、プロジェクトの履歴を追跡しやすくし、特定の変更を見つけ出す際の手がかりとなります。&lt;/p&gt;&#10;&lt;h3 id="プレフィックスの役割"&gt;プレフィックスの役割&#10;&lt;/h3&gt;&lt;p&gt;コミットメッセージにプレフィックスを含めることは、変更の種類を明確にし、プロジェクトの管理を効率化します。例えば、&lt;code&gt;feat&lt;/code&gt;は新機能を、&lt;code&gt;fix&lt;/code&gt;はバグ修正を、&lt;code&gt;docs&lt;/code&gt;はドキュメントの更新を示します。これらのプレフィックスは、コードレビューや履歴の追跡を行う際に、どのような種類の変更が含まれているかを瞬時に理解するのに役立ちます。&lt;/p&gt;&#10;&lt;h3 id="一般的なプレフィックス"&gt;一般的なプレフィックス&#10;&lt;/h3&gt;&lt;p&gt;プロジェクトによって異なることはありますが、一般的には以下のようなプレフィックスが使われます：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;feat&lt;/code&gt;: 新機能の追加&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;fix&lt;/code&gt;: バグの修正&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;docs&lt;/code&gt;: ドキュメントの変更&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;style&lt;/code&gt;: コードのフォーマットやスタイルの変更&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;refactor&lt;/code&gt;: コードのリファクタリング&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;test&lt;/code&gt;: テスト関連の変更&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;これらのプレフィックスを使うことで、コミットメッセージがより情報豊かで、プロジェクトの管理がより容易になります。次のセクションでは、&lt;code&gt;pre-commit&lt;/code&gt;をセットアップし、これらのプレフィックスを自動的にチェックする方法について詳しく説明します。&lt;/p&gt;&#10;&lt;h2 id="pre-commitのセットアップ"&gt;&lt;code&gt;pre-commit&lt;/code&gt;のセットアップ&#10;&lt;/h2&gt;&lt;h3 id="pre-commitのインストール"&gt;&lt;code&gt;pre-commit&lt;/code&gt;のインストール&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;pre-commit&lt;/code&gt;は、開発プロセスを自動化し、コード品質を維持するための強力なツールです。まずは、&lt;code&gt;pre-commit&lt;/code&gt;をインストールする必要があります。Pythonがシステムにインストールされている場合、以下のコマンドで&lt;code&gt;pre-commit&lt;/code&gt;をインストールできます：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install pre-commit&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドは、&lt;code&gt;pre-commit&lt;/code&gt;をグローバルにインストールし、任意のGitリポジトリで使用できるようにします。&lt;/p&gt;&#10;&lt;h3 id="pre-commit-configyamlファイルの設定"&gt;&lt;code&gt;.pre-commit-config.yaml&lt;/code&gt;ファイルの設定&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;pre-commit&lt;/code&gt;を使用するには、リポジトリのルートに&lt;code&gt;.pre-commit-config.yaml&lt;/code&gt;ファイルを作成し、必要な設定を記述する必要があります。このファイルは&lt;code&gt;pre-commit&lt;/code&gt;フックの動作を定義し、どのフックをいつ実行するかを指定します。&lt;/p&gt;&#10;&lt;p&gt;ここでは、例として、基本的な&lt;code&gt;pre-commit&lt;/code&gt;設定を以下に示します：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;repos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://github.com/pre-commit/pre-commit-hooks&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;rev&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v3.4.0 &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# フックのバージョンを指定&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;check-yaml&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;end-of-file-fixer&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この設定例では、公式の&lt;code&gt;pre-commit-hooks&lt;/code&gt;リポジトリからいくつかの基本的なフックを使用しています。各フックは特定のタスクを実行し、コードの品質を向上させるのに役立ちます。&lt;/p&gt;&#10;&lt;h3 id="pre-commitフックのインストール"&gt;&lt;code&gt;pre-commit&lt;/code&gt;フックのインストール&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;.pre-commit-config.yaml&lt;/code&gt;ファイルを設定した後、次のコマンドを使用して&lt;code&gt;pre-commit&lt;/code&gt;フックをリポジトリにインストールします：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pre-commit install&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドは、Gitの&lt;code&gt;pre-commit&lt;/code&gt;フックとして&lt;code&gt;pre-commit&lt;/code&gt;を設定し、コミットを行う際に自動的にこれらのフックが実行されるようにします。&lt;/p&gt;&#10;&lt;p&gt;次のセクションでは、コミットメッセージのプレフィックスをチェックするためのカスタムスクリプトの作成について詳しく説明します。&lt;/p&gt;&#10;&lt;h2 id="カスタムスクリプトの作成"&gt;カスタムスクリプトの作成&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;pre-commit&lt;/code&gt;を使用してコミットメッセージのプレフィックスをチェックするためには、カスタムスクリプトを作成し、それを&lt;code&gt;pre-commit&lt;/code&gt;設定に組み込む必要があります。&lt;/p&gt;&#10;&lt;h3 id="スクリプトの作成"&gt;スクリプトの作成&#10;&lt;/h3&gt;&lt;p&gt;プレフィックスをチェックするスクリプトは、シェルスクリプト（Bashスクリプトなど）で書くことができます。以下は、コミットメッセージが特定のプレフィックスで始まっているかどうかをチェックする簡単なスクリプトの例です：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;commit_regex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;^(feat|fix|docs|style|refactor|test|chore):&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;error_msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;エラー: コミットメッセージは &amp;#39;feat|fix|docs|style|refactor|test|chore:&amp;#39; のいずれかで始まる必要があります。&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; ! grep -qE &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$commit_regex&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$error_msg&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このスクリプトは、コミットメッセージが&lt;code&gt;feat&lt;/code&gt;, &lt;code&gt;fix&lt;/code&gt;, &lt;code&gt;docs&lt;/code&gt;, &lt;code&gt;style&lt;/code&gt;, &lt;code&gt;refactor&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;, &lt;code&gt;chore&lt;/code&gt;のいずれかで始まっていることを確認します。そうでない場合、エラーメッセージを表示し、コミットを拒否します。&lt;/p&gt;&#10;&lt;h3 id="スクリプトのテスト"&gt;スクリプトのテスト&#10;&lt;/h3&gt;&lt;p&gt;スクリプトを作成したら、適切に動作するかどうかをテストすることが重要です。スクリプトをリポジトリのルートに保存し（例：&lt;code&gt;commit-msg-lint.sh&lt;/code&gt;）、実行可能にします：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod +x commit-msg-lint.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そして、異なるコミットメッセージを使ってスクリプトが正しく動作するかを確認します。&lt;/p&gt;&#10;&lt;h3 id="pre-commitにスクリプトを組み込む"&gt;&lt;code&gt;pre-commit&lt;/code&gt;にスクリプトを組み込む&#10;&lt;/h3&gt;&lt;p&gt;カスタムスクリプトを&lt;code&gt;pre-commit&lt;/code&gt;に組み込むには、&lt;code&gt;.pre-commit-config.yaml&lt;/code&gt;ファイルにスクリプトを追加します。以下はその設定例です：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;repos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;local&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;commit-msg-lint&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Check commit message format&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./commit-msg-lint.sh&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;script&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;commit-msg]&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この設定により、&lt;code&gt;pre-commit&lt;/code&gt;がコミットメッセージをチェックする際にカスタムスクリプトが実行されます。&lt;/p&gt;&#10;&lt;p&gt;次のセクションでは、&lt;code&gt;pre-commit&lt;/code&gt;の使用において遭遇する可能性がある一般的なトラブルシューティングについて説明します。&lt;/p&gt;&#10;&lt;h2 id="pre-commitにおけるトラブルシューティング"&gt;&lt;code&gt;pre-commit&lt;/code&gt;におけるトラブルシューティング&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;pre-commit&lt;/code&gt;を使用する際には、いくつかの一般的な問題に直面することがあります。ここでは、これらの問題のいくつかとその解決策について説明します。&lt;/p&gt;&#10;&lt;h3 id="スクリプトが実行不可能な場合"&gt;スクリプトが実行不可能な場合&#10;&lt;/h3&gt;&lt;p&gt;時折、&lt;code&gt;pre-commit&lt;/code&gt;がカスタムスクリプトを実行不可能と認識することがあります。この問題は、スクリプトに適切な実行権限が設定されていない場合に発生することが多いです。スクリプトに実行権限を与えるには、次のコマンドを使用します：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod +x commit-msg-lint.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで、スクリプトは実行可能になります。しかし、これだけでは不十分な場合もあります。Gitのインデックスとファイルシステムの間で実行権限の不一致が生じている場合、&lt;code&gt;git update-index&lt;/code&gt;コマンドを使用してこの問題を解決することができます：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git update-index --chmod&lt;span class="o"&gt;=&lt;/span&gt;+x commit-msg-lint.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="他の一般的な問題"&gt;他の一般的な問題&#10;&lt;/h3&gt;&lt;p&gt;他にも、設定ファイルの誤りや、&lt;code&gt;pre-commit&lt;/code&gt;フックの不適切な設定など、さまざまな問題が発生する可能性があります。これらの問題を解決するには、以下のステップを試みてください：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;.pre-commit-config.yaml&lt;/code&gt; ファイルの設定を再確認し、構文エラーがないかチェックします。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;pre-commit&lt;/code&gt;フックを再インストールします：&lt;code&gt;pre-commit install&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;詳細なエラーメッセージを確認し、具体的な問題の原因を特定します。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;これらの一般的なトラブルシューティング手法を試みることで、ほとんどの問題は解決できるはずです。&lt;/p&gt;&#10;&lt;p&gt;次のセクションでは、&lt;code&gt;pre-commit&lt;/code&gt;の使用におけるベストプラクティスと結論について説明します。&lt;/p&gt;&#10;&lt;h2 id="結論とベストプラクティス"&gt;結論とベストプラクティス&#10;&lt;/h2&gt;&lt;h3 id="pre-commitの有効活用"&gt;&lt;code&gt;pre-commit&lt;/code&gt;の有効活用&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;pre-commit&lt;/code&gt;を使用することで、コードの品質を維持し、開発プロセスを効率化することが可能です。特に、コミットメッセージのプレフィックスを自動的にチェックすることにより、プロジェクトの整理と追跡が容易になります。以下は&lt;code&gt;pre-commit&lt;/code&gt;を最大限に活用するためのいくつかのベストプラクティスです：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;明確なプレフィックスの規則を設定する&lt;/strong&gt;：プロジェクトのニーズに合わせて、明確なプレフィックスの規則を設定し、チーム全体で共有します。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;カスタムフックを適切にテストする&lt;/strong&gt;：新しいフックを追加する際は、適切にテストを行い、予期しない挙動がないことを確認します。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;ドキュメントを整備する&lt;/strong&gt;：&lt;code&gt;pre-commit&lt;/code&gt;の設定や使用するフックに関するドキュメントを整備し、新しいチームメンバーが迅速に理解できるようにします。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="コード品質の維持の重要性"&gt;コード品質の維持の重要性&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;pre-commit&lt;/code&gt;は、コードレビューの負担を軽減し、品質を一定の水準で保つのに役立ちます。自動化されたチェックを導入することで、コーディング規約の遵守、バグの早期発見、一貫性のあるコミットメッセージの作成など、多くの利点があります。&lt;/p&gt;&#10;&lt;h3 id="最後に"&gt;最後に&#10;&lt;/h3&gt;&lt;p&gt;この記事では、&lt;code&gt;pre-commit&lt;/code&gt;を使用してコミットメッセージのプレフィックスをチェックする方法について解説しました。適切なツールとプロセスを取り入れることで、開発プロジェクトの効率と品質を同時に高めることが可能です。これらのプラクティスを活用して、より良いソフトウェア開発を目指しましょう。&lt;/p&gt;&#10;</description></item><item><title>Gitの”Executable … not executable”エラー: 原因と解決法</title><link>https://ai.hack-le.com/git-executable-xxx-not-executable/</link><pubDate>Wed, 15 Nov 2023 16:21:47 +0900</pubDate><guid>https://ai.hack-le.com/git-executable-xxx-not-executable/</guid><description>&lt;h2 id="はじめに"&gt;はじめに&#10;&lt;/h2&gt;&lt;p&gt;Gitと&lt;code&gt;pre-commit&lt;/code&gt;は、現代のソフトウェア開発プロセスにおいて中心的な役割を果たしています。これらのツールを使うことで、開発の効率を高めながらもコードの品質を維持することができます。しかし、これらを日常的に使用する中で、予期しない問題に遭遇することもあります。今回の記事では、そんな一つの典型的な問題、「Executable &lt;code&gt;/path/to/your-script.sh&lt;/code&gt; is not executable」というエラーメッセージに遭遇した際の解決方法を掘り下げます。&lt;/p&gt;&#10;&lt;p&gt;この問題は、Gitリポジトリ内のスクリプトファイルに適切な実行権限が設定されているにも関わらず、&lt;code&gt;pre-commit&lt;/code&gt;フックがそのファイルを実行不可能とみなす状況を指します。それでは、このエラーがどのような状況で発生するのか、見ていきましょう&lt;/p&gt;&#10;&lt;h2 id="背景"&gt;背景&#10;&lt;/h2&gt;&lt;h3 id="gitとpre-commitの基本"&gt;Gitと&lt;code&gt;pre-commit&lt;/code&gt;の基本&#10;&lt;/h3&gt;&lt;p&gt;Gitは、ソースコードのバージョン管理に広く使用されているシステムです。それに対して&lt;code&gt;pre-commit&lt;/code&gt;は、Gitのコミットプロセスにフック（カスタムスクリプト）を組み込むためのツールで、コードの品質を確保するための自動化されたチェックを提供します。これらのフックは、コードがリポジトリにコミットされる前に様々なタイプの検証を行います。&lt;/p&gt;&#10;&lt;h3 id="実行権限の重要性"&gt;実行権限の重要性&#10;&lt;/h3&gt;&lt;p&gt;UNIX系オペレーティングシステム（LinuxやmacOSを含む）では、ファイルの実行権限は非常に重要です。スクリプトやプログラムが実行されるためには、適切な実行権限が設定されている必要があります。この権限は、ファイルシステム上で&lt;code&gt;chmod&lt;/code&gt;コマンドを使って設定されます。&lt;/p&gt;&#10;&lt;h3 id="gitの実行権限の取り扱い"&gt;Gitの実行権限の取り扱い&#10;&lt;/h3&gt;&lt;p&gt;Gitは、ファイルの内容と共に、その実行権限の状態も追跡します。しかし、Gitのインデックス（ステージングエリア）とローカルファイルシステムの間で実行権限の状態に不一致が生じることがあります。特に、異なる環境やファイルシステム間でGitリポジトリが共有される場合、この問題はより複雑になることがあります。&lt;/p&gt;&#10;&lt;h3 id="問題の全体像"&gt;問題の全体像&#10;&lt;/h3&gt;&lt;p&gt;この背景において、&lt;code&gt;Executable not executable&lt;/code&gt;というエラーメッセージは、Gitがスクリプトファイルの実行権限を正しく認識していない場合に発生します。これは、&lt;code&gt;pre-commit&lt;/code&gt; などのツールがスクリプトを実行しようとした際に特に顕著になります。この問題を解決するためには、Gitのインデックスとローカルファイルシステムの間の実行権限の状態を同期させる必要があります。&lt;/p&gt;&#10;&lt;h2 id="問題の詳細"&gt;問題の詳細&#10;&lt;/h2&gt;&lt;p&gt;開発者として、私たちは頻繁にコードの品質を確保し、バグを未然に防ぐために&lt;code&gt;pre-commit&lt;/code&gt;フックを利用します。ある日、私は自分のプロジェクトにカスタムの&lt;code&gt;pre-commit&lt;/code&gt;フックを追加しようとしました。このフックは、コミットメッセージが特定のフォーマットに従っているかどうかをチェックするものでした。&lt;/p&gt;&#10;&lt;p&gt;しかし、このフックを追加した後、コミットしようとすると次のようなエラーメッセージが表示されました：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Executable `/path/to/your-script.sh` is not executable&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このエラーメッセージは、私のスクリプトが実行不可能とみなされていることを示していました。しかし、ファイルには明らかに実行権限が与えられていました。これは、特に混乱を招く問題でした。&lt;/p&gt;&#10;&lt;h2 id="最初のトラブルシューティングの試み"&gt;最初のトラブルシューティングの試み&#10;&lt;/h2&gt;&lt;p&gt;問題の解決に取り組むため、まずは基本的なトラブルシューティングから始めました。最初のステップとして、スクリプトファイルの実行権限を確認しました。ターミナルで以下のコマンドを実行しました：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls -l /path/to/your-script.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;結果は、ファイルが実行権限を持っていることを示していました（&lt;code&gt;-rwxr-xr-x&lt;/code&gt;）。次に、Gitの&lt;code&gt;core.fileMode&lt;/code&gt;設定がファイルの実行権限を正しく追跡しているかどうかを確認しました。この設定は、Gitがファイルの実行権限の変更を検出するかどうかを決定します。&lt;/p&gt;&#10;&lt;p&gt;しかし、これらの基本的なチェックにも関わらず、問題は解決しませんでした。ファイルには明らかに実行権限が付与されているにもかかわらず、&lt;code&gt;pre-commit&lt;/code&gt;は依然としてスクリプトを実行不可能と認識していました。この時点で、問題がもう少し複雑なものであることが明らかになりました。&lt;/p&gt;&#10;&lt;h2 id="解決策git-update-index---chmodx"&gt;解決策：&lt;code&gt;git update-index --chmod=+x&lt;/code&gt;&#10;&lt;/h2&gt;&lt;p&gt;最初のトラブルシューティングのステップが効果を示さなかった後、さらに深く問題を掘り下げました。調査の結果、Gitのインデックスとファイルシステムの間で実行権限の状態に不一致が生じている可能性が浮上しました。この不一致を解消するために、&lt;code&gt;git update-index --chmod=+x&lt;/code&gt; コマンドを使用することにしました。&lt;/p&gt;&#10;&lt;p&gt;このコマンドは、Gitに対して特定のファイルに実行権限があることを明示的に指示します。コマンドを実行することで、Gitのインデックスが更新され、ファイルが実行可能として認識されるようになります。以下のコマンドを実行しました：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git update-index --chmod&lt;span class="o"&gt;=&lt;/span&gt;+x /path/to/your-script.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドを実行した後、再びコミットを試みると、今度は成功しました。エラーメッセージは消え、&lt;code&gt;pre-commit&lt;/code&gt; フックが正常に実行されました。&lt;/p&gt;&#10;&lt;h2 id="なぜこのコマンドが効果的だったのか"&gt;なぜこのコマンドが効果的だったのか&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;git update-index --chmod=+x&lt;/code&gt; コマンドが効果的だった理由は、Gitのインデックスがローカルのファイルシステムの状態と同期していなかったためです。通常、Gitはファイルの内容とメタデータ（この場合は実行権限）を追跡しますが、特定の状況下ではこれらの情報が不一致になることがあります。このコマンドによって、Gitの内部状態が強制的に更新され、スクリプトが実行可能であるという情報がGitのインデックスに正しく反映されました。&lt;/p&gt;&#10;&lt;p&gt;この経験から、特に複数の環境やファイルシステムを跨いで作業する場合には、Gitのインデックスとローカルのファイルシステムの間で生じる可能性のある不一致に注意が必要であることがわかりました。&lt;/p&gt;&#10;&lt;h2 id="他の関連する問題への適用"&gt;他の関連する問題への適用&#10;&lt;/h2&gt;&lt;p&gt;この問題とその解決策は、特定の状況に限定されるものではありません。実際、異なるオペレーティングシステムやGitの設定、さらには異なるバージョンのGitを使用する際にも類似の問題が発生する可能性があります。特に、チーム内で複数の開発環境が混在している場合、Gitのインデックスとファイルシステム間の不一致は一般的な問題となり得ます。&lt;/p&gt;&#10;&lt;p&gt;また、この問題は&lt;code&gt;pre-commit&lt;/code&gt;フックに限定されず、他のGitフックやスクリプト実行の文脈でも発生する可能性があります。そのため、Gitの実行権限に関連するエラーに直面した場合は、&lt;code&gt;git update-index --chmod=+x&lt;/code&gt; コマンドの使用を検討することが有益です。&lt;/p&gt;&#10;&lt;h2 id="結論"&gt;結論&#10;&lt;/h2&gt;&lt;p&gt;この経験から、私たちはGitと&lt;code&gt;pre-commit&lt;/code&gt;の使用におけるいくつかの重要な教訓を学びました。最も重要なのは、Gitのインデックスとローカルのファイルシステムの間に生じる可能性のある不一致に注意を払うことです。また、標準的なトラブルシューティング手法が効果を示さない場合でも、Gitのより高度な機能やコマンドを使用して問題を解決する方法が存在することを理解することも重要です。&lt;/p&gt;&#10;&lt;p&gt;最後に、この問題は、開発者が遭遇する可能性のある一連の問題の一例に過ぎません。技術的な問題に直面した際には、根気強く原因を探求し、コミュニティやドキュメントからのサポートを活用することが不可欠です。このような経験は、技術的スキルの向上だけでなく、より良い開発者に成長するための道の一部です。&lt;/p&gt;&#10;&lt;h2 id="参考リンク"&gt;参考リンク&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://github.com/asottile" target="_blank" rel="noopener"&#10; &gt;&amp;ldquo;Executable &amp;hellip; is not executable&amp;rdquo; error · Issue #1514 · pre-commit/pre-commit&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>Pythonでシェルスクリプトを効率的に実行する: subprocessモジュールの利用</title><link>https://ai.hack-le.com/python-shell/</link><pubDate>Wed, 15 Nov 2023 11:46:58 +0900</pubDate><guid>https://ai.hack-le.com/python-shell/</guid><description>&lt;p&gt;シェルスクリプトやコマンドラインツールをPythonから実行する機能は、多くの開発者にとって有用です。この機能を理解し適切に使いこなすことで、プログラムの自動化、システム管理、データ処理の効率が大幅に向上します。&lt;/p&gt;&#10;&lt;p&gt;しかし、この強力な機能を最大限に活用するためには、いくつかの重要なポイントを理解する必要があります。特に、&lt;code&gt;subprocess&lt;/code&gt; モジュールの &lt;code&gt;shell&lt;/code&gt; と &lt;code&gt;text&lt;/code&gt; パラメータの適切な使用は、コードの安全性、効率、そして読みやすさに大きな影響を与えます。これらのパラメータを正しく理解し使い分けることで、Pythonを用いたシェルスクリプトの実行が、より強力かつ柔軟なものになります。&lt;/p&gt;&#10;&lt;p&gt;この記事では、Pythonでのシェルスクリプト実行の基本から始め、&lt;code&gt;shell&lt;/code&gt; と &lt;code&gt;text&lt;/code&gt; パラメータの詳細な使い方、そしてこれらのパラメータを使用する際のベストプラクティスについて解説していきます。&lt;/p&gt;&#10;&lt;h2 id="基本的なスクリプトの実行"&gt;基本的なスクリプトの実行&#10;&lt;/h2&gt;&lt;p&gt;Pythonでシェルスクリプトや外部コマンドを実行する最も基本的な方法は、標準ライブラリの一部である &lt;code&gt;subprocess&lt;/code&gt; モジュールを使用することです。このモジュールは、Pythonプログラムからシェルコマンドを実行し、その出力を捕捉するための強力な手段を提供します。&lt;/p&gt;&#10;&lt;h3 id="subprocessrun-関数の使用"&gt;&lt;code&gt;subprocess.run()&lt;/code&gt; 関数の使用&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;subprocess.run()&lt;/code&gt; は、外部コマンドを実行し、その結果を取得するための主要な関数です。最も単純な形では、実行したいコマンドの名前を文字列として渡します。例えば、Unix系システムでディレクトリの内容をリストする &lt;code&gt;ls&lt;/code&gt; コマンドを実行するには、以下のように書きます：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;subprocess&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# &amp;#39;ls&amp;#39; コマンドを実行&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ls&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PIPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコードは、現在のディレクトリの内容をリストするコマンドを実行し、その出力を &lt;code&gt;result&lt;/code&gt; 変数に格納します。ここで、&lt;code&gt;stdout=subprocess.PIPE&lt;/code&gt; はコマンドの標準出力をキャプチャするために使用されます。&lt;/p&gt;&#10;&lt;h3 id="実用的なコード例"&gt;実用的なコード例&#10;&lt;/h3&gt;&lt;p&gt;実際の使用例を見てみましょう。たとえば、特定のディレクトリ内のファイルを検索するコマンドを実行したい場合、次のようなコードを書くことができます：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# &amp;#39;grep&amp;#39; コマンドを使用して特定のパターンを検索&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;grep&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;特定のパターン&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ファイル名&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PIPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 結果の出力&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このスクリプトは、指定されたファイル内で「特定のパターン」を検索し、見つかった行を表示します。ここで、&lt;code&gt;decode('utf-8')&lt;/code&gt; は、標準出力を人間が読める形式（UTF-8エンコードされたテキスト）に変換します。&lt;/p&gt;&#10;&lt;h2 id="shell-パラメータ"&gt;&lt;code&gt;shell&lt;/code&gt; パラメータ&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;subprocess.run()&lt;/code&gt; 関数を使用する際に重要な選択の一つが &lt;code&gt;shell&lt;/code&gt; パラメータの設定です。このパラメータは、コマンドがどのように実行されるかを制御し、セキュリティと機能の両面に影響を与えます。&lt;/p&gt;&#10;&lt;h3 id="shelltrue-の利用"&gt;&lt;code&gt;shell=True&lt;/code&gt; の利用&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;shell=True&lt;/code&gt; を指定すると、指定されたコマンドはシェル（bash, cmd.exeなど）を介して実行されます。これにより、シェルの機能（ワイルドカード、パイプライン、リダイレクトなど）を利用することができます。たとえば、複数のコマンドをパイプラインで連結する場合、&lt;code&gt;shell=True&lt;/code&gt; が必要です。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# &amp;#39;grep&amp;#39; コマンドをパイプラインで使用&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ls | grep &amp;#39;特定のパターン&amp;#39;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PIPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ただし、このモードはセキュリティリスクが伴います。特に、不適切に制御された入力からコマンドを構築する場合、シェルインジェクション攻撃に対して脆弱になる可能性があります。そのため、&lt;code&gt;shell=True&lt;/code&gt; は信頼できる入力に対してのみ使用すべきです。&lt;/p&gt;&#10;&lt;h3 id="shellfalse-の安全性"&gt;&lt;code&gt;shell=False&lt;/code&gt; の安全性&#10;&lt;/h3&gt;&lt;p&gt;デフォルトでは、&lt;code&gt;shell&lt;/code&gt; パラメータは &lt;code&gt;False&lt;/code&gt; に設定されています。このモードでは、コマンドはシェルを介さずに直接実行されます。これにより、セキュリティが強化され、シェルインジェクション攻撃のリスクが低減されます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# シェルを介さずに &amp;#39;grep&amp;#39; コマンドを実行&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;grep&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;特定のパターン&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ファイル名&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PIPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このモードでは、シェルの特殊な機能を使用することはできませんが、より安全で予測可能なコマンド実行が可能です。&lt;/p&gt;&#10;&lt;h2 id="出力の処理text-パラメータ"&gt;出力の処理：&lt;code&gt;text&lt;/code&gt; パラメータ&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;subprocess.run()&lt;/code&gt; 関数を使用する際にもう一つ重要な選択肢が &lt;code&gt;text&lt;/code&gt; パラメータです。このパラメータは、コマンドの出力をどのように扱うかを制御し、使いやすさとデータの扱い方に大きな影響を与えます。&lt;/p&gt;&#10;&lt;h3 id="texttrue-の利点"&gt;&lt;code&gt;text=True&lt;/code&gt; の利点&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;text=True&lt;/code&gt; を指定すると、コマンドの出力は文字列（&lt;code&gt;str&lt;/code&gt; 型）として返されます。これにより、出力を直接テキストとして処理することができ、コードがより簡潔かつ直感的になります。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# &amp;#39;grep&amp;#39; コマンドの出力を文字列として扱う&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;grep&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;特定のパターン&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ファイル名&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PIPE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 出力は直接文字列として扱える&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このモードは、コマンドの出力をテキスト処理する場合に非常に便利です。例えば、出力を検索したり、ファイルに書き込んだり、ユーザーに表示したりする際に役立ちます。&lt;/p&gt;&#10;&lt;h3 id="textfalse-の場合"&gt;&lt;code&gt;text=False&lt;/code&gt; の場合&#10;&lt;/h3&gt;&lt;p&gt;デフォルトの &lt;code&gt;text=False&lt;/code&gt; は、出力をバイト列（&lt;code&gt;bytes&lt;/code&gt; 型）として返します。これは、バイナリデータを扱う場合や特定のエンコーディングでデータを処理する場合に適しています。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# &amp;#39;grep&amp;#39; コマンドの出力をバイト列として扱う&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;grep&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;特定のパターン&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ファイル名&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PIPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# バイト列をデコードして文字列に変換&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このモードでは、出力をデコードする追加のステップが必要ですが、バイナリデータや特殊なエンコーディングを扱う際には必要不可欠です。&lt;/p&gt;&#10;&lt;h3 id="使い分け"&gt;使い分け&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;text&lt;/code&gt; パラメータの設定は、出力の扱い方とプログラムの使いやすさに直接影響します。テキストベースの出力を扱う場合は &lt;code&gt;text=True&lt;/code&gt; が便利ですが、バイナリデータや特殊なエンコーディングを扱う場合（（例えば、画像データや特定の文字セットを扱う場合）には &lt;code&gt;text=False&lt;/code&gt; を選択すると良いでしょう。&lt;/p&gt;&#10;&lt;h2 id="エラー処理とデバッグ"&gt;エラー処理とデバッグ&#10;&lt;/h2&gt;&lt;p&gt;Pythonでシェルスクリプトを実行する際には、エラー処理とデバッグが重要な役割を果たします。適切なエラー処理と効果的なデバッグ手法を用いることで、信頼性の高いスクリプトを作成することができます。&lt;/p&gt;&#10;&lt;h3 id="エラー処理の重要性"&gt;エラー処理の重要性&#10;&lt;/h3&gt;&lt;p&gt;シェルスクリプトの実行中には様々なエラーが発生する可能性があります。これには、コマンドが見つからない、コマンドが失敗する、間違った引数が渡されるなどが含まれます。これらのエラーを適切に処理することで、スクリプトの堅牢性を高めることができます。&lt;/p&gt;&#10;&lt;h4 id="try-except-ブロックの使用"&gt;&lt;code&gt;try-except&lt;/code&gt; ブロックの使用&#10;&lt;/h4&gt;&lt;p&gt;Pythonの &lt;code&gt;try-except&lt;/code&gt; ブロックを使用して、&lt;code&gt;subprocess.run()&lt;/code&gt; からの例外を捕捉し、適切に処理することができます。例えば、以下のコードは、コマンド実行中に発生したエラーを捕捉し、エラーメッセージを表示します：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;subprocess&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ls&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;-l&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CalledProcessError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;エラー: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここで、&lt;code&gt;check=True&lt;/code&gt; はコマンドが非ゼロの終了ステータスで終了した場合に &lt;code&gt;CalledProcessError&lt;/code&gt; を発生させるために使用されます。&lt;/p&gt;&#10;&lt;h3 id="デバッグのヒント"&gt;デバッグのヒント&#10;&lt;/h3&gt;&lt;p&gt;デバッグの際には、コマンドの正確な出力やエラーメッセージが重要な手がかりとなります。以下に、デバッグを容易にするためのヒントをいくつか紹介します。&lt;/p&gt;&#10;&lt;h4 id="標準出力と標準エラーのログ記録"&gt;標準出力と標準エラーのログ記録&#10;&lt;/h4&gt;&lt;p&gt;コマンドの標準出力と標準エラーをログに記録することで、問題の診断が容易になります。例えば：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ls&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;-l&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PIPE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PIPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;標準出力:&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;標準エラー:&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この方法では、コマンドの実行結果を詳細に確認することができます。&lt;/p&gt;&#10;&lt;h4 id="エラーコードの確認"&gt;エラーコードの確認&#10;&lt;/h4&gt;&lt;p&gt;コマンドが失敗した場合、エラーコード（終了ステータス）を確認することが有効です。例えば：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ls&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;-l&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PIPE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PIPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;returncode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;エラーコード: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;returncode&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このエラーコードは、コマンドが何故失敗したかを理解するための手がかりとなります。&lt;/p&gt;&#10;&lt;h2 id="結論"&gt;結論&#10;&lt;/h2&gt;&lt;p&gt;この記事を通じて、Pythonを使用してシェルスクリプトを実行する際の重要な側面を探求しました。&lt;code&gt;subprocess&lt;/code&gt; モジュールの &lt;code&gt;shell&lt;/code&gt; と &lt;code&gt;text&lt;/code&gt; パラメータの適切な使用方法を理解することで、Pythonスクリプトの機能と安全性を最大限に引き出すことができます。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;code&gt;shell&lt;/code&gt; パラメータ&lt;/strong&gt;は、シェルの特性を活用する際に重要ですが、セキュリティリスクを考慮して慎重に使用する必要があります。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;code&gt;text&lt;/code&gt; パラメータ&lt;/strong&gt;は、コマンドの出力を文字列として扱うかバイト列として扱うかを決定し、出力の扱いやすさを大きく左右します。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;また、&lt;strong&gt;エラー処理とデバッグ&lt;/strong&gt;の重要性を理解し、これらのテクニックを適切に適用することで、より堅牢で信頼性の高いスクリプトを作成できます。&lt;/p&gt;&#10;&lt;p&gt;Pythonを使用したシェルスクリプトの実行は、多くの自動化とプロセス管理タスクにおいて強力なツールです。この記事が提供するガイダンスとヒントを活用することで、あなたのプロジェクトにおいても、より効率的で安全なスクリプトの実装が可能になることを願っています。&lt;/p&gt;&#10;</description></item><item><title>メタデータを含まないGitHub.comからGitHub Enterpriseへのリポジトリ移行ガイド</title><link>https://ai.hack-le.com/github-com-github-enterprise/</link><pubDate>Tue, 14 Nov 2023 13:29:37 +0900</pubDate><guid>https://ai.hack-le.com/github-com-github-enterprise/</guid><description>&lt;p&gt;&lt;strong&gt;導入&lt;/strong&gt;: GitHubからGitHub Enterpriseへのリポジトリ移行の際は、まずメタデータの移行をするかどうかが重要な判断となります。GitHubリポジトリのメタデータ（Issueやプルリクエストなど）の移行を行うかどうかを判断する際に考慮すべきポイントは以下の通りです：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;プロジェクトの歴史の重要性&lt;/strong&gt;: 過去のIssueやプルリクエストが将来のプロジェクト運営に重要な情報を含んでいる場合、これらのデータを移行する価値があります。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;プロジェクトの継続性&lt;/strong&gt;: 新しい環境でのプロジェクトの継続性を保つために、過去の議論や決定の履歴を参照できることが重要な場合は、メタデータの移行を検討すべきです。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;リソースと技術力&lt;/strong&gt;: メタデータの移行は複雑で時間とリソースを要するプロセスです。十分な技術力とリソースがあるかどうかを評価してください。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;プロジェクトの将来計画&lt;/strong&gt;: プロジェクトが新しいフェーズに入っており、過去のデータがそれほど関連性を持たない場合、メタデータの移行は必要ないかもしれません。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;これらの要素を総合的に検討し、プロジェクトのニーズとリソースに基づいて決定を下すことが重要です。&lt;/p&gt;&#10;&lt;p&gt;Issueやプルリクエスト（PR）などのメタデータを含まなくてよい場合、移行は比較的簡単なプロセスです。ここでは、コードとコミット履歴のみを移行する手順を詳細に説明します。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;手順&lt;/strong&gt;:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;新しいリポジトリの作成&lt;/strong&gt;:&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;GitHub Enterpriseにログインし、新しいリポジトリを作成します。このリポジトリは空である必要があります。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;ol start="2"&gt;&#10;&lt;li&gt;&lt;strong&gt;ローカルリポジトリの準備&lt;/strong&gt;:&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;移行するローカルリポジトリで作業している場合、最新の状態に更新しておきます（&lt;code&gt;git pull&lt;/code&gt;）。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;ol start="3"&gt;&#10;&lt;li&gt;&lt;strong&gt;リモートURLの変更&lt;/strong&gt;:&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;リポジトリのリモートURLをGitHub Enterpriseの新しいリポジトリURLに変更します。これには&lt;code&gt;git remote set-url origin [新しいURL]&lt;/code&gt;コマンドを使用します。（ &lt;code&gt;.git/config&lt;/code&gt;を参照することで変更を確認できます）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;ol start="4"&gt;&#10;&lt;li&gt;&lt;strong&gt;コードのプッシュ&lt;/strong&gt;:&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;git push -u origin master&lt;/code&gt;（または対象のブランチ名）を使用して、コードを新しいリポジトリにプッシュします。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;チームメンバーへの指示&lt;/strong&gt;:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;チームの他のメンバーも、自分のローカルリポジトリで同じリモートURLの変更を行う必要があります。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;注意点&lt;/strong&gt;:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;この方法では、コードとコミット履歴のみが移行されます。GitHubのメタデータ（Issue、PRなど）は移行されません。これらの情報を移行したい場合は、追加の手順が必要です。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;結論&lt;/strong&gt;: GitHub.comからGitHub Enterpriseへのリポジトリ移行は、上記の手順を実行することで、簡単かつ効率的に行うことができます。ただし、プロジェクトの要件に応じて、メタデータの移行も検討してください。&lt;/p&gt;&#10;</description></item><item><title>[Mac] シェルスクリプトでファイルを日付別に整理する方法</title><link>https://ai.hack-le.com/mac-shell-date-folder/</link><pubDate>Tue, 31 Oct 2023 22:34:55 +0900</pubDate><guid>https://ai.hack-le.com/mac-shell-date-folder/</guid><description>&lt;h4 id="はじめに"&gt;はじめに&#10;&lt;/h4&gt;&lt;p&gt;ファイルの整理は作業効率を上げる重要なステップです。特に、多くのファイルがあるディレクトリでは、ファイルを日付別に分類することで目的のファイルを素早く見つけられるようになります。&lt;/p&gt;&#10;&lt;p&gt;この記事では、シェルスクリプトを使用してファイルを最終変更日に基づいて日付別のフォルダに自動で移動する方法を紹介します。&lt;/p&gt;&#10;&lt;h4 id="手順"&gt;手順&#10;&lt;/h4&gt;&lt;ol&gt;&#10;&lt;li&gt;ターミナルを開き、整理したいファイルがあるディレクトリに移動します。&lt;/li&gt;&#10;&lt;li&gt;以下のシェルスクリプトを作成します。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -d &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;stat -f &lt;span class="s2"&gt;&amp;#34;%Sm&amp;#34;&lt;/span&gt; -t &lt;span class="s2"&gt;&amp;#34;%Y-%m-%d&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; ! -d &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$date&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mkdir &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$date&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mv &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$date&lt;/span&gt;&lt;span class="s2"&gt;/&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;&#10;&lt;li&gt;スクリプトを保存し、実行権限を与えます。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod +x script.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;&#10;&lt;li&gt;スクリプトを実行します。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./script.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="まとめ"&gt;まとめ&#10;&lt;/h4&gt;&lt;p&gt;この記事では、シェルスクリプトを使用してファイルを最終変更日に基づいて日付別のフォルダに自動で分類する方法を紹介しました。簡単なスクリプトで作業効率が大幅に向上します。是非お試しください。&lt;/p&gt;&#10;</description></item><item><title>Fishスクリプトでファイル名に日付時刻を追加する</title><link>https://ai.hack-le.com/fish-file-timestamp/</link><pubDate>Fri, 29 Sep 2023 07:52:46 +0900</pubDate><guid>https://ai.hack-le.com/fish-file-timestamp/</guid><description>&lt;p&gt;Fishシェルは、その美しいシンタックスと強力な機能で知られています。この記事では、Fishスクリプトを使用してカレントディレクトリの各ファイル名にタイムスタンプ（ここでは日付と時刻の文字列）を追加する方法を紹介します。このスクリプトは、既にタイムスタンプが付いているファイルは無視するので、複数回実行しても安全です。また、ディレクトリは対象外です。&lt;/p&gt;&#10;&lt;p&gt;以下に、タイムスタンプを追加するためのスクリプトを示します。&lt;/p&gt;&#10;&lt;p&gt;ワンライナースクリプト:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; -f &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; and not string match -r &lt;span class="s2"&gt;&amp;#34;^[0-9]{14}_&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt; &amp;gt; /dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; timestamp &lt;span class="o"&gt;(&lt;/span&gt;date -r &lt;span class="nv"&gt;$file&lt;/span&gt; +&lt;span class="s2"&gt;&amp;#34;%Y%m%d%H%M%S&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; mv &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$timestamp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;_&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; end&lt;span class="p"&gt;;&lt;/span&gt; end&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;分割バージョン:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; -f &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; and not string match -r &lt;span class="s2"&gt;&amp;#34;^[0-9]{14}_&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt; &amp;gt; /dev/null&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;set&lt;/span&gt; timestamp &lt;span class="o"&gt;(&lt;/span&gt;date -r &lt;span class="nv"&gt;$file&lt;/span&gt; +&lt;span class="s2"&gt;&amp;#34;%Y%m%d%H%M%S&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mv &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$timestamp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;_&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; end&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;end&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;bashバージョン:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -f &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; ! &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^&lt;span class="o"&gt;[&lt;/span&gt;0-9&lt;span class="o"&gt;]{&lt;/span&gt;14&lt;span class="o"&gt;}&lt;/span&gt;_ &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;timestamp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date -r &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; +&lt;span class="s2"&gt;&amp;#34;%Y%m%d%H%M%S&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mv &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;timestamp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これらのスクリプトは、カレントディレクトリの全てのファイルをループし、各ファイルに対して以下の操作を行います&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;code&gt;test -f&lt;/code&gt;コマンドを使用して、アイテムがファイルであることを確認します（ディレクトリは除外されます）。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;string match&lt;/code&gt;コマンドを使用して、ファイル名が既にタイムスタンプを含んでいるかどうかを確認します。&lt;/li&gt;&#10;&lt;li&gt;タイムスタンプが含まれていない場合、&lt;code&gt;date&lt;/code&gt;コマンドを使用してファイルのタイムスタンプを生成します。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;mv&lt;/code&gt;コマンドを使用して、生成されたタイムスタンプとアンダースコアをファイル名の先頭に追加し、ファイル名を変更します。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;このスクリプトは、ファイルの整理と管理を容易にし、ファイルのバージョン管理を簡単に行えるようにします。&lt;/p&gt;&#10;</description></item><item><title>サブディレクトリ下の画像ファイルをwebp形式に変換するシェルスクリプト</title><link>https://ai.hack-le.com/sub-directory-image-webp/</link><pubDate>Sun, 24 Sep 2023 15:38:27 +0900</pubDate><guid>https://ai.hack-le.com/sub-directory-image-webp/</guid><description>&lt;h2 id="はじめに"&gt;はじめに&#10;&lt;/h2&gt;&lt;p&gt;この記事では、サブディレクトリに存在する&lt;code&gt;.PNG&lt;/code&gt;, &lt;code&gt;.png&lt;/code&gt;, &lt;code&gt;.jpg&lt;/code&gt;, &lt;code&gt;.jpeg&lt;/code&gt;, &lt;code&gt;.JPG&lt;/code&gt;, &lt;code&gt;.JPEG&lt;/code&gt; ファイルを&lt;code&gt;.webp&lt;/code&gt;形式に変換し、元の画像ファイルを削除するスクリプトを、BashとFishシェルでそれぞれ実装する方法について説明します。&lt;/p&gt;&#10;&lt;h2 id="必要なツール"&gt;必要なツール&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;ImageMagick (convert コマンドが使用されます)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="fishのスクリプト"&gt;Fishのスクリプト&#10;&lt;/h2&gt;&lt;h3 id="コード"&gt;コード&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; img in /*.PNG /*.png /*.jpg /*.jpeg /*.JPG /*.JPEG&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;set&lt;/span&gt; name &lt;span class="o"&gt;(&lt;/span&gt;basename &lt;span class="nv"&gt;$img&lt;/span&gt; .&lt;span class="o"&gt;(&lt;/span&gt;string split -r -m1 &lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt; &lt;span class="nv"&gt;$img&lt;/span&gt;&lt;span class="o"&gt;)[&lt;/span&gt;2&lt;span class="o"&gt;])&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;set&lt;/span&gt; dir &lt;span class="o"&gt;(&lt;/span&gt;dirname &lt;span class="nv"&gt;$img&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;set&lt;/span&gt; new_path &lt;span class="nv"&gt;$dir&lt;/span&gt;/&lt;span class="nv"&gt;$name&lt;/span&gt;.webp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; convert &lt;span class="nv"&gt;$img&lt;/span&gt; &lt;span class="nv"&gt;$new_path&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; rm &lt;span class="nv"&gt;$img&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;end&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ワンライナー"&gt;ワンライナー&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; img in /*.PNG /*.png /*.jpg /*.jpeg /*.JPG /*.JPEG&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; name &lt;span class="o"&gt;(&lt;/span&gt;basename &lt;span class="nv"&gt;$img&lt;/span&gt; .&lt;span class="o"&gt;(&lt;/span&gt;string split -r -m1 &lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt; &lt;span class="nv"&gt;$img&lt;/span&gt;&lt;span class="o"&gt;)[&lt;/span&gt;2&lt;span class="o"&gt;])&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; dir &lt;span class="o"&gt;(&lt;/span&gt;dirname &lt;span class="nv"&gt;$img&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; new_path &lt;span class="nv"&gt;$dir&lt;/span&gt;/&lt;span class="nv"&gt;$name&lt;/span&gt;.webp&lt;span class="p"&gt;;&lt;/span&gt; convert &lt;span class="nv"&gt;$img&lt;/span&gt; &lt;span class="nv"&gt;$new_path&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; rm &lt;span class="nv"&gt;$img&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; end&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="bashのスクリプト"&gt;Bashのスクリプト&#10;&lt;/h2&gt;&lt;h3 id="コード-1"&gt;コード&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -type f &lt;span class="se"&gt;\(&lt;/span&gt; -iname &lt;span class="s1"&gt;&amp;#39;*.png&amp;#39;&lt;/span&gt; -o -iname &lt;span class="s1"&gt;&amp;#39;*.jpg&amp;#39;&lt;/span&gt; -o -iname &lt;span class="s1"&gt;&amp;#39;*.jpeg&amp;#39;&lt;/span&gt; &lt;span class="se"&gt;\)&lt;/span&gt; -exec sh -c &lt;span class="s1"&gt;&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; f=&amp;#34;{}&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; d=$(dirname &amp;#34;$f&amp;#34;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; b=$(basename &amp;#34;$f&amp;#34;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; nf=&amp;#34;${d}/$(basename &amp;#34;${b%.*}&amp;#34;).webp&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; convert &amp;#34;$f&amp;#34; &amp;#34;$nf&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; rm &amp;#34;$f&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ワンライナー-1"&gt;ワンライナー&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -type f &lt;span class="se"&gt;\(&lt;/span&gt; -iname &lt;span class="s1"&gt;&amp;#39;*.png&amp;#39;&lt;/span&gt; -o -iname &lt;span class="s1"&gt;&amp;#39;*.jpg&amp;#39;&lt;/span&gt; -o -iname &lt;span class="s1"&gt;&amp;#39;*.jpeg&amp;#39;&lt;/span&gt; &lt;span class="se"&gt;\)&lt;/span&gt; -exec sh -c &lt;span class="s1"&gt;&amp;#39;f=&amp;#34;{}&amp;#34;; d=$(dirname &amp;#34;$f&amp;#34;); b=$(basename &amp;#34;$f&amp;#34;); nf=&amp;#34;${d}/$(basename &amp;#34;${b%.*}&amp;#34;).webp&amp;#34;; convert &amp;#34;$f&amp;#34; &amp;#34;$nf&amp;#34;; rm &amp;#34;$f&amp;#34;&amp;#39;&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="結論"&gt;結論&#10;&lt;/h2&gt;&lt;p&gt;以上がBashとFishで&lt;code&gt;.PNG&lt;/code&gt;, &lt;code&gt;.png&lt;/code&gt;, &lt;code&gt;.jpg&lt;/code&gt;, &lt;code&gt;.jpeg&lt;/code&gt;, &lt;code&gt;.JPG&lt;/code&gt;, &lt;code&gt;.JPEG&lt;/code&gt; ファイルを&lt;code&gt;.webp&lt;/code&gt;に変換するスクリプトの書き方です。これにより、簡単に画像ファイルの形式を変更することができます。&lt;/p&gt;&#10;</description></item><item><title>文字列混じりのファイル名の数字部分をゼロ埋めするスクリプト</title><link>https://ai.hack-le.com/file-zero-padding/</link><pubDate>Sun, 24 Sep 2023 15:02:56 +0900</pubDate><guid>https://ai.hack-le.com/file-zero-padding/</guid><description>&lt;h2 id="背景"&gt;背景&#10;&lt;/h2&gt;&lt;p&gt;Linux や macOS などのシステムでよく使われる &lt;code&gt;ls&lt;/code&gt; コマンドで出力されたファイル名リストが整列されていないと、作業効率が下がることがあります。特に、ファイル名の後ろに数字がついている場合、&lt;code&gt;a1.png&lt;/code&gt;, &lt;code&gt;a2.png&lt;/code&gt;, &lt;code&gt;a10.png&lt;/code&gt; のように整列されていないことがよくあります。&lt;/p&gt;&#10;&lt;p&gt;この問題を解決するために、Fish シェルと Bash シェルで数字部分をゼロ埋めするスクリプトを作成します。&lt;/p&gt;&#10;&lt;h2 id="fish-シェル"&gt;Fish シェル&#10;&lt;/h2&gt;&lt;p&gt;Fish シェルでは以下のようにスクリプトを書きます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *.png&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;set&lt;/span&gt; name &lt;span class="o"&gt;(&lt;/span&gt;string match -r &lt;span class="s2"&gt;&amp;#34;[a-zA-Z]+&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;set&lt;/span&gt; num &lt;span class="o"&gt;(&lt;/span&gt;string match -r &lt;span class="s2"&gt;&amp;#34;\d+&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;set&lt;/span&gt; new_num &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;%02d&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;$num&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mv &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$name$new_num&lt;/span&gt;&lt;span class="s2"&gt;.png&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;end&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ワンライナー"&gt;ワンライナー&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *.png&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; name &lt;span class="o"&gt;(&lt;/span&gt;string match -r &lt;span class="s2"&gt;&amp;#34;[a-zA-Z]+&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; num &lt;span class="o"&gt;(&lt;/span&gt;string match -r &lt;span class="s2"&gt;&amp;#34;\d+&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; new_num &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;%02d&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;$num&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; mv &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$name$new_num&lt;/span&gt;&lt;span class="s2"&gt;.png&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; end&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="bash-シェル"&gt;Bash シェル&#10;&lt;/h2&gt;&lt;p&gt;Bash シェルでは以下のようにスクリプトを書きます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *.png&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s2"&gt;&amp;#34;^[a-zA-Z]*&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;num&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s2"&gt;&amp;#34;[0-9]*&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;new_num&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;%02d&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;$num&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mv &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$name$new_num&lt;/span&gt;&lt;span class="s2"&gt;.png&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ワンライナー-1"&gt;ワンライナー&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *.png&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s2"&gt;&amp;#34;^[a-zA-Z]*&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;num&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s2"&gt;&amp;#34;[0-9]*&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;new_num&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;%02d&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;$num&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; mv &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$name$new_num&lt;/span&gt;&lt;span class="s2"&gt;.png&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;この記事で紹介したスクリプトを使えば、&lt;code&gt;ls&lt;/code&gt; コマンドで出力されるファイル名の数字部分をゼロ埋めして、整列されたリストを得ることができます。Fish シェルと Bash シェルの両方で実現可能です。&lt;/p&gt;&#10;</description></item><item><title>カレントディレクトリのサブディレクトリを.cbz形式で圧縮するBashワンライナー</title><link>https://ai.hack-le.com/current-cbz/</link><pubDate>Sat, 23 Sep 2023 00:46:20 +0900</pubDate><guid>https://ai.hack-le.com/current-cbz/</guid><description>&lt;p&gt;自炊ユーザ必携スクリプト。カレントディレクトリにあるjpgの塊のサブフォルダを.cbzにするワンライナをChatGPTに書かせたのであった。昔コツコツ書いていた自作のスニペットもう全部不要……。&lt;/p&gt;&#10;&lt;h3 id="イントロ"&gt;イントロ&#10;&lt;/h3&gt;&lt;p&gt;BashおよびFishシェルは、UNIX系オペレーティングシステムにおいて、コマンドラインから操作するためのインターフェースを提供します。これらのシェルを利用することで、システムの様々なタスクを一行のコマンドで実行できます。本記事では、これらのシェルを使用して、サブディレクトリを&lt;code&gt;.cbz&lt;/code&gt;形式で圧縮する方法を紹介します。&lt;/p&gt;&#10;&lt;h3 id="bashでの実行"&gt;Bashでの実行&#10;&lt;/h3&gt;&lt;p&gt;Bashでは、以下のワンライナーを使用することで、カレントディレクトリに存在する全てのサブディレクトリを&lt;code&gt;.cbz&lt;/code&gt;形式で圧縮できます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;for dir in */; do dir_name=&amp;#34;${dir%/}&amp;#34;; zip -r &amp;#34;$dir_name.zip&amp;#34; &amp;#34;$dir_name&amp;#34;; mv &amp;#34;$dir_name.zip&amp;#34; &amp;#34;$dir_name.cbz&amp;#34;; done&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="fishでの実行"&gt;Fishでの実行&#10;&lt;/h3&gt;&lt;p&gt;Fishシェルでは、少し構文が異なります。以下のワンライナーを使用します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;for dir in */; set dir_name (string trim -r -c &amp;#39;/&amp;#39; $dir); zip -r $dir_name.zip $dir_name; mv $dir_name.zip $dir_name.cbz; end&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="プロセスの説明"&gt;プロセスの説明&#10;&lt;/h3&gt;&lt;ol&gt;&#10;&lt;li&gt;カレントディレクトリの全サブディレクトリをリストアップします。&lt;/li&gt;&#10;&lt;li&gt;各サブディレクトリに対して、ディレクトリ名から末尾のスラッシュ(&lt;code&gt;/&lt;/code&gt;)を削除し、その名前を変数にセットします。&lt;/li&gt;&#10;&lt;li&gt;次に、そのディレクトリをzip形式で圧縮します。&lt;/li&gt;&#10;&lt;li&gt;最後に、生成されたzipファイルの拡張子を&lt;code&gt;.zip&lt;/code&gt;から&lt;code&gt;.cbz&lt;/code&gt;に変更します。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;.cbz形式は通常、コミックブックのリーダーアプリで使用される形式で、基本的にはzipアーカイブです。このワンライナーは、特にコミックや画像集の整理に有用で、シンプルでありながら、大量のディレクトリを効率的に圧縮するのに役立ちます。&lt;/p&gt;&#10;</description></item><item><title>シェルスクリプトで括弧を取り除く: BashとFishシェルのワンライナー</title><link>https://ai.hack-le.com/shell-remove-brackets/</link><pubDate>Sat, 23 Sep 2023 00:26:41 +0900</pubDate><guid>https://ai.hack-le.com/shell-remove-brackets/</guid><description>&lt;p&gt;例によってFishスクリプトの備忘録。これのあとにゼロ埋めすること多し。&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://ai.hack-le.com/shell-zero-padding/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;シェルスクリプトでファイル名をゼロ埋めする方法: BashとFishシェル&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/shell-zero-padding/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://ai.hack-le.com/images/uploads/2023/09/6f9b1fd1af0f8fc4c9c4770d681c8deb.webp" alt="シェルスクリプトでファイル名をゼロ埋めする方法: BashとFishシェル" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;h3 id="はじめに"&gt;はじめに:&#10;&lt;/h3&gt;&lt;p&gt;カレントディレクトリに存在する &lt;code&gt;(数字).jpg&lt;/code&gt; 形式のファイル名から括弧 &lt;code&gt;()&lt;/code&gt; を取り除く方法について、BashシェルとFishシェルでの簡単なワンライナーを紹介します。&lt;/p&gt;&#10;&lt;h3 id="bash-シェル"&gt;Bash シェル:&#10;&lt;/h3&gt;&lt;p&gt;Bash シェルでは、次のワンライナーで、カレントディレクトリにある全ての &lt;code&gt;(*).jpg&lt;/code&gt; ファイル名から括弧を取り除くことができます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *&lt;span class="s1"&gt;&amp;#39;(&amp;#39;&lt;/span&gt;*&lt;span class="s1"&gt;&amp;#39;)&amp;#39;&lt;/span&gt;*.jpg&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; mv &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="p"&gt;//&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *&lt;span class="s1"&gt;&amp;#39;)&amp;#39;&lt;/span&gt;*.jpg&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; mv &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="p"&gt;//&lt;/span&gt;&lt;span class="se"&gt;\)&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これにより、例えば &lt;code&gt;(123).jpg&lt;/code&gt; というファイル名が &lt;code&gt;123.jpg&lt;/code&gt; に変更されます。&lt;/p&gt;&#10;&lt;h3 id="fish-シェル"&gt;Fish シェル:&#10;&lt;/h3&gt;&lt;p&gt;Fish シェルでは、以下のワンライナーで同様の操作が可能です。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *&lt;span class="s1"&gt;&amp;#39;(&amp;#39;&lt;/span&gt;*&lt;span class="s1"&gt;&amp;#39;)&amp;#39;&lt;/span&gt;*.jpg&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; new_file &lt;span class="o"&gt;(&lt;/span&gt;string replace -ra &lt;span class="s1"&gt;&amp;#39;[()]&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; mv &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="nv"&gt;$new_file&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; end&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この Fish シェルのワンライナーは、カレントディレクトリに存在する &lt;code&gt;(数字).jpg&lt;/code&gt; 形式のファイル名から、左括弧 &lt;code&gt;(&lt;/code&gt; と右括弧 &lt;code&gt;)&lt;/code&gt; を両方正しく取り除きます。&lt;/p&gt;&#10;&lt;h3 id="まとめ"&gt;まとめ:&#10;&lt;/h3&gt;&lt;p&gt;ファイル名から特定の文字を取り除くことは、ファイルの整理や管理を助けます。Bash シェルと Fish シェルのどちらでも、簡単なワンライナーでこの操作を行うことができます。&lt;/p&gt;&#10;</description></item><item><title>シェルスクリプトでファイル名をゼロ埋めする方法: BashとFishシェル</title><link>https://ai.hack-le.com/shell-zero-padding/</link><pubDate>Sat, 23 Sep 2023 00:22:50 +0900</pubDate><guid>https://ai.hack-le.com/shell-zero-padding/</guid><description>&lt;p&gt;画像のファイル整理中とかに時々出てくるシチュエーションのbash, fishのワンライナスニペット。毎回ChatGPTに聞くのも煩わしいので備忘録メモ。&lt;/p&gt;&#10;&lt;h2 id="はじめに"&gt;はじめに:&#10;&lt;/h2&gt;&lt;p&gt;数値で構成されたファイル名（例： &lt;code&gt;1.jpg&lt;/code&gt; 、 &lt;code&gt;10.jpg&lt;/code&gt; ）を3桁のゼロ埋め形式（例： &lt;code&gt;001.jpg&lt;/code&gt; 、 &lt;code&gt;010.jpg&lt;/code&gt; ）に変更する方法について解説します。ここでは、BashシェルとFishシェルの両方で利用可能なワンライナーコマンドを紹介します。&lt;/p&gt;&#10;&lt;h2 id="bash-シェル"&gt;Bash シェル:&#10;&lt;/h2&gt;&lt;p&gt;Bash シェルでは、次のワンライナーコマンドで、カレントディレクトリにある全ての &lt;code&gt;.jpg&lt;/code&gt; ファイル名をゼロ埋めできます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *.jpg&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^&lt;span class="o"&gt;([&lt;/span&gt;0-9&lt;span class="o"&gt;]&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;jpg$ &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mv &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;%03d.jpg&amp;#34;&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASH_REMATCH&lt;/span&gt;&lt;span class="p"&gt;[1]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドは、カレントディレクトリに存在する全ての &lt;code&gt;.jpg&lt;/code&gt; ファイルを対象にし、数字だけのファイル名を3桁のゼロ埋めに変更します。&lt;/p&gt;&#10;&lt;h2 id="fish-シェル"&gt;Fish シェル:&#10;&lt;/h2&gt;&lt;p&gt;Fish シェルでは、次のワンライナーで同等の操作が可能です。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *.jpg&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -qE &lt;span class="s1"&gt;&amp;#39;^[0-9]+\.jpg$&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; -l num &lt;span class="o"&gt;(&lt;/span&gt;string match -r &lt;span class="s1"&gt;&amp;#39;([0-9]+)&amp;#39;&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;)[&lt;/span&gt;2&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; mv &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;%03d.jpg&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;$num&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; end&lt;span class="p"&gt;;&lt;/span&gt; end&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Fish シェルでこのコマンドを実行すると、カレントディレクトリにある数字だけの &lt;code&gt;.jpg&lt;/code&gt; ファイルが、3桁のゼロ埋め形式に変更されます。&lt;/p&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ:&#10;&lt;/h2&gt;&lt;p&gt;シェルスクリプトを用いて、数値で構成されたファイル名をゼロ埋め形式に変更することは、ファイルの整理や管理を助けます。Bash シェルと Fish シェルのどちらも、簡単に同等の操作を実行することができます。&lt;/p&gt;&#10;</description></item><item><title>fishシェルの環境変数設定：-Ux vs -gx</title><link>https://ai.hack-le.com/fish-ux-vs-gx/</link><pubDate>Sun, 17 Sep 2023 12:50:48 +0900</pubDate><guid>https://ai.hack-le.com/fish-ux-vs-gx/</guid><description>&lt;p&gt;環境変数の設定方法いつも忘れてしまうので、メモっておく。&lt;/p&gt;&#10;&lt;h2 id="イントロ"&gt;イントロ&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;fish&lt;/code&gt;シェルは、その直感的な機能とユーザーフレンドリーな設定方法で多くの開発者から支持を受けています。この記事では、&lt;code&gt;fish&lt;/code&gt;シェルで環境変数を設定する2つの一般的な方法、&lt;code&gt;-Ux&lt;/code&gt;と&lt;code&gt;-gx&lt;/code&gt;の違いと、それぞれの利点と欠点について詳しく説明します。&lt;/p&gt;&#10;&lt;h2 id="2つの方法"&gt;2つの方法&#10;&lt;/h2&gt;&lt;p&gt;大別して、&lt;code&gt;-Ux&lt;/code&gt;を使う方法と&lt;code&gt;-gx&lt;/code&gt;を使う方法があります。&lt;/p&gt;&#10;&lt;h3 id="-uxユニバーサル変数としてエクスポート"&gt;&lt;code&gt;-Ux&lt;/code&gt;：ユニバーサル変数としてエクスポート&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;set -U&lt;/code&gt;：変数を永続的なユニバーサル変数として設定します。これは、すべてのfishインスタンスで共有され、セッション間で保存される変数です。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;set -x&lt;/code&gt;：変数をエクスポートします。これにより、その変数が子プロセスに利用可能になります。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;例として、&lt;code&gt;MY_VARIABLE&lt;/code&gt;という名前の環境変数を永続的に設定し、それをエクスポートしたい場合、次のようにコマンドを使用します：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -Ux MY_VARIABLE &amp;#34;Some Value&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドを実行すると、&lt;code&gt;MY_VARIABLE&lt;/code&gt;はすべてのfishインスタンスと子プロセスで利用可能となります。そして、システムを再起動してもこの設定は保持されます。&lt;/p&gt;&#10;&lt;p&gt;ユニバーサル変数を削除する場合は、&lt;code&gt;set -e&lt;/code&gt;オプションとともに変数の名前を指定します：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -e MY_VARIABLE&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドにより、指定されたユニバーサル変数が削除されます。&lt;/p&gt;&#10;&lt;h4 id="メリット"&gt;メリット:&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;永続性&lt;/strong&gt;: すべてのセッション間で保持され、システム再起動後も失われません。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;共有&lt;/strong&gt;: すべての&lt;code&gt;fish&lt;/code&gt;インスタンス間で変数が共有されます。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;インタラクティブ設定&lt;/strong&gt;: コマンドラインから直接変数を設定・変更が可能です。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="デメリット"&gt;デメリット:&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;オーバーヘッド&lt;/strong&gt;: 多くのユニバーサル変数を使用すると、起動時のオーバーヘッドが増加する可能性があります。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;混乱の原因&lt;/strong&gt;: 変数の変更が他の全ての&lt;code&gt;fish&lt;/code&gt;インスタンスに影響します。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="オススメするケース"&gt;オススメするケース:&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;共通の設定&lt;/strong&gt;: 複数の &lt;code&gt;fish&lt;/code&gt; セッションやインスタンス間で共有したい設定がある場合。例えば、特定のプログラムのパスを追加したいときなど。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;一時的な変更&lt;/strong&gt;: インタラクティブに変数を変更し、その設定を暫定的にすべてのセッションで利用したい場合。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;マシン全体の設定&lt;/strong&gt;: 複数のユーザーアカウント間で共有したい設定がある場合。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="-gxグローバル変数としてエクスポート"&gt;&lt;code&gt;-gx&lt;/code&gt;：グローバル変数としてエクスポート&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;-g&lt;/code&gt; オプションを使用して設定された変数は、グローバル変数として保存されます。&lt;/li&gt;&#10;&lt;li&gt;これは現在のセッション内でのみ存在し、新しいセッションやターミナルウィンドウで利用することはできません。&lt;/li&gt;&#10;&lt;li&gt;セッションが終了すると、グローバル変数も消失します。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;いくつかの代表的な設定パターンを列挙します。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;PATH変数にディレクトリを追加する&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -gx PATH $PATH /path/to/your/directory&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;新しい環境変数を設定する&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -gx MY_VARIABLE &amp;#34;Some Value&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;既存の環境変数の値を変更する&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;set -gx PATH &amp;#34;/new/path:$PATH&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これらの設定を、設定ファイルに記述することで、セッションを開始する時に読み込まれます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nano ~/.config/fish/config.fish&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="メリット-1"&gt;メリット:&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;明確な初期化&lt;/strong&gt;: 変数の初期化が明確になり、文書化しやすくなります。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;セッション固有&lt;/strong&gt;: 特定のセッションにのみ変数や設定を適用可能です。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="デメリット-1"&gt;デメリット:&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;非永続性&lt;/strong&gt;: セッションが終了すると変数は消失します。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;変更の手間&lt;/strong&gt;: 変数の変更のためには設定ファイルを編集し、新しいセッションを開始または設定ファイルを再読み込みする必要があります。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="オススメするケース-1"&gt;オススメするケース:&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;セッション固有の設定&lt;/strong&gt;: あるセッションに特定の変数や設定を適用したいが、他のセッションには影響を与えたくない場合。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;明確な管理&lt;/strong&gt;: セッションの設定や起動時の動作を明確に制御したい場合。&lt;code&gt;config.fish&lt;/code&gt; に明確な指示を書くことで、どの変数がセットされているか、なぜそれがそうなっているかを文書化しやすくなります。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;多数の変数を設定&lt;/strong&gt;: 多くの環境変数を設定する場合、それらを一か所（&lt;code&gt;config.fish&lt;/code&gt;）にまとめることで、管理や変更が容易になります。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="-gxを推奨"&gt;&lt;code&gt;-gx&lt;/code&gt;を推奨&#10;&lt;/h2&gt;&lt;p&gt;一般的なシナリオでは、&lt;code&gt;-gx&lt;/code&gt;オプションを&lt;code&gt;config.fish&lt;/code&gt;に記述する方法が推奨されます。これにより、設定の一元管理が容易になり、意図しない変数の共有や競合を避けることができます。しかしながら、特定の状況やニーズに応じて&lt;code&gt;-Ux&lt;/code&gt;オプションを選択することも有効です。&lt;/p&gt;&#10;&lt;p&gt;環境変数の設定方法は、その用途やニーズに応じて最も適した方法を選択することが重要です。どちらの方法を選ぶかは、具体的な使用ケースやニーズに応じて異なるため、各プロジェクトやタスクの要件をよく理解し、適切な選択をするよう努めましょう。&lt;/p&gt;&#10;&lt;h2 id="寸評"&gt;寸評&#10;&lt;/h2&gt;&lt;p&gt;こういう話題は得意だよねChatGPT。基本的には設定ファイルに書いてるかな。持ち運べるし。&lt;/p&gt;&#10;</description></item><item><title>fish,bashでのPNGとJPGファイルのWebPへの一括変換</title><link>https://ai.hack-le.com/fishbash-png-jpg-webp/</link><pubDate>Wed, 26 Jul 2023 14:28:43 +0900</pubDate><guid>https://ai.hack-le.com/fishbash-png-jpg-webp/</guid><description>&lt;p&gt;単純な内容だけれどよく使うかつよく忘れるので。これ、本当はBardに書かせようと思っていたんだよね。でも、Bardはfishスクリプトだと言っているのにBashのスクリプトしか書いてくれなかった。あと日本語も通じづらくて、かなり明確に指示してやる必要がある。結論として、ChatGPT-4にはまだ及ばないなぁ、と。アホになっているという噂のChatGPT-4だが、それでも今出ているAIチャットでは一番なんじゃないだろうか。&lt;/p&gt;&#10;&lt;p&gt;ということで、記事を書かせた。&lt;/p&gt;&#10;&lt;h2 id="イントロ"&gt;イントロ&#10;&lt;/h2&gt;&lt;p&gt;こんにちは、皆さん。&lt;/p&gt;&#10;&lt;p&gt;今日はLinuxシェルを使ってカレントディレクトリのPNGとJPGファイルを一括でWebP形式に変換する方法についてご紹介します。この作業は、fish shellとbashの両方で実行可能です。Macのターミナルや、Windows上のWSL2でももちろん実行可能です。&lt;/p&gt;&#10;&lt;p&gt;前提条件として、この記事で用いる&lt;code&gt;convert&lt;/code&gt;コマンドはImageMagickの一部なので、事前にシステムにインストールしておく必要があります。&lt;/p&gt;&#10;&lt;h2 id="fish-shellでの変換"&gt;Fish Shellでの変換&#10;&lt;/h2&gt;&lt;p&gt;まず、Fish Shellを使った方法から見ていきましょう。以下のワンライナーを実行すると、カレントディレクトリの全ての&lt;code&gt;.png&lt;/code&gt;と&lt;code&gt;.jpg&lt;/code&gt;ファイルが&lt;code&gt;.webp&lt;/code&gt;に変換されます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *.png *.jpg&lt;span class="p"&gt;;&lt;/span&gt; convert &lt;span class="nv"&gt;$file&lt;/span&gt; -format webp &lt;span class="o"&gt;(&lt;/span&gt;basename -s &lt;span class="o"&gt;(&lt;/span&gt;string match -r &lt;span class="s2"&gt;&amp;#34;\..+&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;.webp&lt;span class="p"&gt;;&lt;/span&gt; end&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドは、まず&lt;code&gt;*.png *.jpg&lt;/code&gt;というパターンで全てのPNGとJPGファイルを選択します。そして、&lt;code&gt;convert&lt;/code&gt;コマンド（ImageMagickの一部として提供されている）を使ってそれぞれのファイルを&lt;code&gt;.webp&lt;/code&gt;フォーマットに変換します。&lt;/p&gt;&#10;&lt;h2 id="bashでの変換"&gt;Bashでの変換&#10;&lt;/h2&gt;&lt;p&gt;次に、Bashを使った方法を見ていきましょう。以下のワンライナーを実行すると、同様にカレントディレクトリの全ての&lt;code&gt;.png&lt;/code&gt;と&lt;code&gt;.jpg&lt;/code&gt;ファイルが&lt;code&gt;.webp&lt;/code&gt;に変換されます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; file in *.&lt;span class="o"&gt;{&lt;/span&gt;png,jpg&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; convert &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; -format webp &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.webp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドでは、&lt;code&gt;*.{png,jpg}&lt;/code&gt;というパターンマッチングを使用して.pngと.jpgファイルを一度に全て選択します。そして、&lt;code&gt;&amp;quot;${file%.*}.webp&amp;quot;&lt;/code&gt;という表現を用いて元のファイル名から拡張子を取り除き、新しい&lt;code&gt;.webp&lt;/code&gt;拡張子を追加します。&lt;/p&gt;&#10;&lt;h2 id="結論"&gt;結論&#10;&lt;/h2&gt;&lt;p&gt;以上が、Fish ShellとBashを使ってPNGとJPGファイルをWebPに一括変換する方法です。このようなスクリプトは、特に大量の画像ファイルを効率的に変換したいときに非常に便利です。&lt;/p&gt;&#10;&lt;h2 id="寸評"&gt;寸評&#10;&lt;/h2&gt;&lt;p&gt;実家のような安心感。なんだかんだでChatGPT-4パイセンが今のところナンバーワンですわ……。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;fishでカレントディレクトリのすべてのpngをwebpにconvertするワンライナ&lt;/li&gt;&#10;&lt;li&gt;いいね。pngだけではなくjpgについてもやりたい時は？&lt;/li&gt;&#10;&lt;li&gt;ありがとう。 ここまでの内容を、ブログの記事としてまとめてください。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;質問の数もシンプル。&lt;/p&gt;&#10;</description></item><item><title>Node.jsのバージョン一覧をCLIから取得する方法</title><link>https://ai.hack-le.com/node-js-cli/</link><pubDate>Wed, 19 Jul 2023 15:54:41 +0900</pubDate><guid>https://ai.hack-le.com/node-js-cli/</guid><description>&lt;p&gt;fishではnvmのサポートが微妙ということで、Node.jsのバージョン管理にはvoltaを使うことにした。が、voltaは配布されているNodeのバージョン一覧を取得するコマンドがない。まぁ &lt;code&gt;volta install node@18&lt;/code&gt;とかでざっくりインストールすればいいからだと思うが。まぁそうは言っても、バージョン一覧をCLIから取得したいなぁと思って、ChatGPT-4に聞いた。&lt;/p&gt;&#10;&lt;h2 id="環境"&gt;環境&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;M2 Pro MacBook Pro 14インチ&lt;/li&gt;&#10;&lt;li&gt;macOS 13.4.1&lt;/li&gt;&#10;&lt;li&gt;fish 3.6.1&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="はじめに"&gt;はじめに&#10;&lt;/h2&gt;&lt;p&gt;Node.jsはJavaScriptをサーバーサイドで実行するための環境で、そのバージョン管理は重要な作業の一部です。今日は、Node.jsの公式配布元から利用可能なすべてのNode.jsのバージョンを一覧表示する方法を紹介します。これにより、特定のバージョンが存在するか確認したり、どのバージョンをインストールすべきか決定する際の参考にすることができます。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="nodejsのバージョン一覧を取得するコマンド"&gt;Node.jsのバージョン一覧を取得するコマンド&#10;&lt;/h2&gt;&lt;p&gt;以下のコマンドを使用します：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -s https://nodejs.org/dist/ &lt;span class="p"&gt;|&lt;/span&gt; grep -Eo &lt;span class="s1"&gt;&amp;#39;v[0-9]+\.[0-9]+\.[0-9]+/&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed &lt;span class="s1"&gt;&amp;#39;s/\///g&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sort -V&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下のような出力が得られます：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;v0.1.14&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;v0.1.14&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;v0.1.15&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;v0.1.15&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;v20.1.0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;v20.2.0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;v20.2.0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;v20.3.0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;v20.3.0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;v20.3.1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;v20.3.1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;v20.4.0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;v20.4.0&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコマンドは以下の操作を行っています：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;code&gt;curl -s https://nodejs.org/dist/&lt;/code&gt;：Node.jsの公式配布元からHTMLを取得します。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;grep -Eo 'v[0-9]+\.[0-9]+\.[0-9]+/'&lt;/code&gt;：取得したHTMLからバージョン番号を抽出します。&lt;code&gt;-E&lt;/code&gt;オプションは拡張正規表現を使用することを指定し、&lt;code&gt;-o&lt;/code&gt;オプションは一致した部分のみを出力します。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;sed 's/\///g'&lt;/code&gt;：バージョン番号の末尾にあるスラッシュ(&lt;code&gt;/&lt;/code&gt;)を削除します。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;sort -V&lt;/code&gt;：バージョン番号を順番に並べ替えます。&lt;code&gt;-V&lt;/code&gt;オプションはバージョン番号のような形式を正しくソートすることを指定します。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="注意点"&gt;注意点&#10;&lt;/h2&gt;&lt;p&gt;このコマンドはUNIXベースのシステム（LinuxやmacOSなど）で動作します。Windowsの場合、同等の操作を行うためにはWindows Subsystem for Linux（WSL）や、cygwin、git bashなどのツールが必要です。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;Node.jsのバージョン管理は、プロジェクトの安定性や互換性を確保するために重要です。今回紹介したコマンドを使えば、CLIから簡単にNode.jsのバージョン一覧を取得でき、適切なバージョンの選択に役立つでしょう。&lt;/p&gt;&#10;&lt;h2 id="寸評"&gt;寸評&#10;&lt;/h2&gt;&lt;p&gt;質問一発で返ってきそうだが、以外にも引っかかっている。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;node.jsのマネージャであるvoltaでnodeを入れたいのだが、インストールできるバージョンの一覧はどのように取得できるのか&lt;/li&gt;&#10;&lt;li&gt;コマンドラインからNode.jsで配布されているバージョンを簡単に取得するにはどうしたらよいか&lt;/li&gt;&#10;&lt;li&gt;grep: invalid option &amp;ndash; P usage: grep [-abcdDEFGHhIiJLlMmnOopqRSsUVvwXxZz] [-A num] [-B num] [-C[num]] [-e pattern] [-f file] [&amp;ndash;binary-files=value] [&amp;ndash;color=when] [&amp;ndash;context[=num]] [&amp;ndash;directories=action] [&amp;ndash;label] [&amp;ndash;line-buffered] [&amp;ndash;null] [pattern] [file &amp;hellip;] とエラーが出た。Macのターミナルで実行した。&lt;/li&gt;&#10;&lt;li&gt;何も出力されない。awkによる抽出が失敗していると見られる。curlのレスポンスを一部抜粋した。これを見て修正できるか。（コードを貼る）&lt;/li&gt;&#10;&lt;li&gt;うまく動いた！ 備忘録としてブログにまとめたい。CLIからnodeのバージョン一覧を取得する方法について、ブログ記事としてまとめてくれ。適切に見出しを入れてくれ。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;失敗したが、実際の出力を貼ることでうまくいった。&lt;/p&gt;&#10;</description></item><item><title>【Macユーザー必見】右クリックから画像をwebpに瞬時に変換しよう！</title><link>https://ai.hack-le.com/mac-webp/</link><pubDate>Sun, 16 Jul 2023 14:13:24 +0900</pubDate><guid>https://ai.hack-le.com/mac-webp/</guid><description>&lt;p&gt;内容はタイトルのとおりで、クイックアクションを使ってwebpに変換するコマンドを作成するというもの。要はこれを作る。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://ai.hack-le.com/images/uploads/2023/07/a468cf58e75fa2612957a0d6740ebdf5.jpg"&gt;&lt;/p&gt;&#10;&lt;p&gt;これは普通に便利だよ。では以下、ChatGPT-4によるテンション高めの記事本文。&lt;/p&gt;&#10;&lt;h2 id="イントロ"&gt;イントロ&#10;&lt;/h2&gt;&lt;p&gt;こんにちは、今日はMacの便利な機能であるクイックアクションを使って、画像をwebp形式に変換する方法をご紹介します。この方法を使えば、画像ファイルを右クリックするだけで簡単にwebp形式に変換することができます。&lt;/p&gt;&#10;&lt;p&gt;手順は以下の通りです。&lt;/p&gt;&#10;&lt;h2 id="準備"&gt;準備&#10;&lt;/h2&gt;&lt;p&gt;今回の作業のための準備をしましょう。いくつかのツールを入れる必要があります。&lt;/p&gt;&#10;&lt;h3 id="homebrewのインストール"&gt;Homebrewのインストール&#10;&lt;/h3&gt;&lt;p&gt;まずはHomebrewをインストールします。HomebrewはMacでソフトウェアを簡単に管理するためのパッケージ管理システムです。既にインストールしてある方はこの手順をスキップしてください。ターミナルを開き、以下のコマンドを実行します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/bin/bash -c &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="libwebpのインストール"&gt;libwebpのインストール&#10;&lt;/h3&gt;&lt;p&gt;次に、Homebrewを使ってlibwebpをインストールします。libwebpはGoogleが開発した画像形式であるwebpへの変換ツールです。ターミナルで以下のコマンドを実行します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;brew install webp&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="クイックアクションの作成"&gt;クイックアクションの作成&#10;&lt;/h2&gt;&lt;p&gt;Automatorを開き、「新規ドキュメント」を作成します。「ドキュメントの種類」の選択画面が表示されたら、「クイックアクション」を選択します。選択したら、下記のような設定をしますので、手順を説明します。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://ai.hack-le.com/images/uploads/2023/07/7374f7834a56835f276a2c2bcaba8f00.jpg"&gt;&lt;/p&gt;&#10;&lt;p&gt;「ワークフローが受け取る現在の項目」の項目で「イメージファイル」を選択し、さらにその右隣の「検索対象」のドロップダウンから「Finder」を選択します。&lt;/p&gt;&#10;&lt;p&gt;左側のパネルから「ユーティリティ」カテゴリを開き、「シェルスクリプトを実行」を右側の空白領域にドラッグアンドドロップします。&lt;/p&gt;&#10;&lt;p&gt;シェルスクリプトアクションに以下のコマンドを入力します（「入力の引き渡し方法」は「引数として」に設定）。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; f in &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;do&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /usr/local/bin/cwebp &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; -o &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.webp&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;著者注記: あらかじめ &lt;code&gt;which cwebp&lt;/code&gt; でcwebpのパスを調べておく。 &lt;code&gt;/opt/homebrew/bin/cwebp&lt;/code&gt;にする必要があるかも。&lt;/p&gt;&#10;&lt;h2 id="クイックアクションの実行"&gt;クイックアクションの実行&#10;&lt;/h2&gt;&lt;p&gt;メニューバーの「ファイル」から「保存」を選び、クイックアクションに名前をつけて保存します。この名前がコマンドの名前になるため、「webpに変換」などのわかりやすい名前にしましょう。&lt;/p&gt;&#10;&lt;p&gt;これで準備は完了です。Finderから画像ファイルを右クリックすると、コンテクストメニューの「クイックアクション」の中に新しく作成したアクションが表示されます。選択すると、選択した画像ファイルがwebp形式に変換され、元の画像と同じ場所に保存されます。&lt;/p&gt;&#10;&lt;h2 id="注意点画質と元画像の削除について"&gt;注意点、画質と元画像の削除について&#10;&lt;/h2&gt;&lt;h3 id="元画像の削除"&gt;元画像の削除&#10;&lt;/h3&gt;&lt;p&gt;注意点として、このコマンドは元の画像ファイルを保持しつつ新しいwebpファイルを作成します。元の画像を削除したい場合は、上記のシェルスクリプトに&lt;code&gt;rm &amp;quot;$f&amp;quot;&lt;/code&gt;コマンドを追加します。これにより、変換後のwebpファイルが作成された後に元の画像が削除されます。&lt;/p&gt;&#10;&lt;p&gt;以下に修正したコードを示します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; f in &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;do&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /usr/local/bin/cwebp &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; -o &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.webp&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; rm &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコードは元のファイルを完全に削除するため、誤って重要なファイルを削除しないように十分注意してください。実行前にバックアップを取るなど、データの安全対策を忘れずに行ってください。&lt;/p&gt;&#10;&lt;h3 id="画像の品質"&gt;画像の品質&#10;&lt;/h3&gt;&lt;p&gt;また、出力されるwebp画像の品質はデフォルトの設定（75％）になります。品質設定を変更するには、上記のcwebpコマンドに-qオプションを追加します（例：-q 90）。&lt;/p&gt;&#10;&lt;p&gt;以上で、Macのクイックアクションを使って画像を簡単にwebpに変換する方法のご紹介を終えます。ぜひ試してみてください。&lt;/p&gt;&#10;&lt;h2 id="寸評"&gt;寸評&#10;&lt;/h2&gt;&lt;p&gt;有能。シェルスクリプトを交えつつAutomatorを使った完全なガイド。これはGoogle検索だと中々出てこない。&lt;/p&gt;&#10;&lt;p&gt;以下のような質問をした。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Macのクイックアクションで、画像をwebpに変換するアクションを作成したい！&lt;/li&gt;&#10;&lt;li&gt;素晴らしい。完璧だ。UIは日本語のほうがよかったが、そこは僕が補足しよう。 クイックアクションで画像ファイルを右クリックから手軽にwebpに変換できるようにする方法について、ブログ記事としてまとめてくれ&lt;/li&gt;&#10;&lt;li&gt;元の画像を削除したい場合のコードについても書いたほうがいいな。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;解説のUIが思いっきり英語だったので、僕のほうで直すといったところ、なんだか日本語化しようと頑張っていたが、結果間違っていたのでそこは僕が修正した。相変わらずディテールを間違えるChatGPT。こうして人間の仕事は微調整になっていくのか……。&lt;/p&gt;&#10;</description></item><item><title>WSL2でMacのようにクリップボードを操作する方法</title><link>https://ai.hack-le.com/wsl2-mac-clipboard/</link><pubDate>Sun, 16 Jul 2023 00:52:55 +0900</pubDate><guid>https://ai.hack-le.com/wsl2-mac-clipboard/</guid><description>&lt;p&gt;Macだとpbcopyやpbpasteといったコマンドでクリップボードの内容をターミナル上で扱うことができて、これが非常に便利。Windowsでも同じことができないか、ChatGPT-4に聞いたところ非常にうまくいったので、ブログ記事としてまとめさせた。&lt;/p&gt;&#10;&lt;h2 id="イントロ"&gt;イントロ&#10;&lt;/h2&gt;&lt;p&gt;Windows Subsystem for Linux 2（WSL2）は、Windows上でLinuxを動作させることができる強力なツールです。しかし、Macユーザーが利用できる便利な&lt;code&gt;pbcopy&lt;/code&gt;と&lt;code&gt;pbpaste&lt;/code&gt;コマンドのような、クリップボードに直接アクセスする機能がデフォルトではありません。この記事では、WSL2でこれらのコマンドを模倣する方法を解説します。&lt;/p&gt;&#10;&lt;h2 id="windowsのクリップボードにコピー"&gt;Windowsのクリップボードにコピー&#10;&lt;/h2&gt;&lt;p&gt;WSL2からWindowsのクリップボードにコピーするには、Windows側の&lt;code&gt;clip.exe&lt;/code&gt;コマンドを利用します。例えば次のようにします:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;テキスト&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; clip.exe&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="windowsのクリップボードからペースト"&gt;Windowsのクリップボードからペースト&#10;&lt;/h2&gt;&lt;p&gt;逆に、WindowsのクリップボードからWSL2にペーストするには、&lt;code&gt;powershell.exe&lt;/code&gt;を利用します:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;powershell.exe -command &lt;span class="s1"&gt;&amp;#39;Get-Clipboard&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="コマンドを短くする"&gt;コマンドを短くする&#10;&lt;/h2&gt;&lt;p&gt;これらのコマンドは有用ですが、特にペーストの方は長く、打つのが面倒かもしれません。それを解決するために、&lt;code&gt;pbcopy&lt;/code&gt;と&lt;code&gt;pbpaste&lt;/code&gt;というエイリアスを定義します。&lt;/p&gt;&#10;&lt;h3 id="bashの場合"&gt;bashの場合&#10;&lt;/h3&gt;&lt;p&gt;bash シェルを使っている場合、&lt;code&gt;.bashrc&lt;/code&gt; ファイルに以下のエイリアスを追加します:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;pbcopy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;clip.exe&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;pbpaste&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;powershell.exe -command Get-Clipboard&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そして、ターミナルを再起動するか、以下のコマンドを実行して新しいエイリアスを利用可能にします:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで、Macのように &lt;code&gt;pbcopy&lt;/code&gt; と &lt;code&gt;pbpaste&lt;/code&gt; コマンドを使用することができます。&lt;/p&gt;&#10;&lt;h3 id="fishの場合"&gt;fishの場合&#10;&lt;/h3&gt;&lt;p&gt;Fish shellでは、関数として定義して、&lt;code&gt;config.fish&lt;/code&gt;ファイルに保存することで、同様の機能を実現できます。&lt;/p&gt;&#10;&lt;p&gt;まず、Fish shellで新しい関数を作成します:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;function&lt;/span&gt; pbcopy&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; -n &lt;span class="nv"&gt;$argv&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; clip.exe&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;end&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;function&lt;/span&gt; pbpaste&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; powershell.exe -command &lt;span class="s1"&gt;&amp;#39;Get-Clipboard&amp;#39;&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;end&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次に、これらの関数を保存します。以下のコマンドは、作成した関数を &lt;code&gt;~/.config/fish/functions/&lt;/code&gt; ディレクトリに保存します：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;funcsave pbcopy&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;funcsave pbpaste&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以上の手順で、&lt;code&gt;pbcopy&lt;/code&gt;と&lt;code&gt;pbpaste&lt;/code&gt;の機能をFish shellで使用できるようになります。新たなシェルセッションでもこれらの関数が使用可能になるよう、手動で定義するのではなく、&lt;code&gt;funcsave&lt;/code&gt; コマンドを使って保存することが重要です。&lt;/p&gt;&#10;&lt;h2 id="結論"&gt;結論&#10;&lt;/h2&gt;&lt;p&gt;これにより、WSL2でもMacのようにクリップボードを操作することが可能になります。この機能を利用すれば、シェルスクリプトやコマンドラインツールから直接クリップボードにアクセスすることができ、作業の効率を上げることができます。&lt;/p&gt;&#10;&lt;h2 id="寸評"&gt;寸評&#10;&lt;/h2&gt;&lt;p&gt;これでWSL2でも&lt;code&gt;pbcopy&lt;/code&gt;や&lt;code&gt;pbpaste&lt;/code&gt;といったコマンドを使えるようになった。pbcopyで一行改行ができるのが少し気になるが……。まぁでもこれは便利だね。&lt;/p&gt;&#10;&lt;p&gt;以下、質問した内容。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Macではpbcoyやpbpasteでクリップボードの内容をターミナルで利用できますが、WindowsのWSL2で同じようなことはできませんか&lt;/li&gt;&#10;&lt;li&gt;いいね。しかし、clip.exeはいいがペーストのほうはコマンドが長すぎる。&lt;/li&gt;&#10;&lt;li&gt;最高だ。完璧に&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;まちがって途中で送信してしまった&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;ol start="4"&gt;&#10;&lt;li&gt;それでは、この素晴らしい方法を、いつでも思い出して使えるように、あるいは他の人もできるように、ブログ記事としてまとめてくれ。&lt;/li&gt;&#10;&lt;li&gt;fishだとどうなる？&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;今回は記事の方もあまり手直ししていない。&lt;/p&gt;&#10;</description></item><item><title>WordPressのエディタ選択: Gutenbergとクラシックエディタの存在理由と選択ガイド</title><link>https://ai.hack-le.com/wordpress-gutenberg/</link><pubDate>Fri, 30 Jun 2023 00:45:50 +0900</pubDate><guid>https://ai.hack-le.com/wordpress-gutenberg/</guid><description>&lt;p&gt;これは私がクラシックエディタの存在意義についてChatGPT-4に書かせたものである。私自身は複数のブログを運営しており、Gutenbergをメインにしているものもあれば、クラシックエディタをメインにしているものもある。どちらにも良いところと悪いところがあるわけだが、基本的には新しいエディタであるGutenbergが推奨される。というか、Gutenbergが出てもう何年もたっているのに、未だにクラシックエディタは健在である。それはいったいぜんたいどういうことだ、ということについての記事である。&lt;/p&gt;&#10;&lt;h2 id="はじめに"&gt;はじめに&#10;&lt;/h2&gt;&lt;p&gt;WordPressユーザーにとって、記事やページの作成と編集は日々の重要なタスクの一つです。そのため、使用するエディタの選択は、作業の効率性、使いやすさ、そして最終的なコンテンツの品質に大きな影響を与えます。WordPressでは、現在、二つの主要なエディターが提供されています: Gutenbergとクラシックエディタ。しかし、これらの違いとどちらを選ぶべきかは一見すると明確ではありません。ここでは、両者の特性を詳しく見ていき、どちらのエディタがあなたに適しているかを判断するためのガイドを提供します。&lt;/p&gt;&#10;&lt;h2 id="gutenbergとクラシックエディタの違い"&gt;Gutenbergとクラシックエディタの違い&#10;&lt;/h2&gt;&lt;p&gt;まず最初に、それぞれのエディタの特性と機能を理解することが重要です。&lt;/p&gt;&#10;&lt;p&gt;Gutenbergは、ブロックベースのエディタで、視覚的なレイアウトとデザインに重点を置いています。それは特に、画像、ビデオ、カラムレイアウトなどを頻繁に使用するユーザーにとって有用です。視覚的なエディタとして、ユーザーは自由にブロックを移動、編集、または削除することができ、より直感的なビジュアル編集体験を提供します。&lt;/p&gt;&#10;&lt;p&gt;一方、クラシックエディタはより伝統的なWordPressエディタで、テキストエディタと視覚エディタの間で切り替える選択肢があります。これはテキストベースのコンテンツとHTMLコードを直接編集する能力を必要とする人々にとっては便利な機能かもしれません。&lt;/p&gt;&#10;&lt;h2 id="なぜクラシックエディタは依然として存在しているのか"&gt;なぜクラシックエディタは依然として存在しているのか&#10;&lt;/h2&gt;&lt;p&gt;それぞれのエディタには独自の利点があり、WordPressユーザーの間でそれぞれ異なるニーズを満たしています。Gutenbergは多くの点で魅力的なエディタですが、すべてのユーザーや状況に対して最適とは限りません。その一部を以下に挙げます。&lt;/p&gt;&#10;&lt;h3 id="テキストヘビーなブログ"&gt;テキストヘビーなブログ&#10;&lt;/h3&gt;&lt;p&gt;Gutenbergは視覚的な要素とレイアウトが多いサイトに最適化されています。しかし、主にテキストベースのコンテンツを提供するブログや、コードスニペットや引用などの特定のテキスト要素を頻繁に使用するウェブサイトでは、クラシックエディタの方がより直感的で使いやすい場合があります。&lt;/p&gt;&#10;&lt;h3 id="高度なカスタマイゼーションの必要性"&gt;高度なカスタマイゼーションの必要性&#10;&lt;/h3&gt;&lt;p&gt;Gutenbergは便利なブロックを提供していますが、それらのブロックのカスタマイゼーションは限定的です。HTMLやCSSのようなウェブ言語に精通していて、独自のカスタマイゼーションを高度に適用したいユーザーにとっては、クラシックエディタの方が直接的なコード編集の能力を提供するため、より魅力的な選択肢となるかもしれません。&lt;/p&gt;&#10;&lt;h3 id="特定のプラグインやテーマの依存"&gt;特定のプラグインやテーマの依存&#10;&lt;/h3&gt;&lt;p&gt;一部のプラグインやテーマは、Gutenbergではなくクラシックエディタに最適化されているか、または両方をサポートしていません。したがって、これらのプラグインやテーマに依存している場合、Gutenbergの使用は制限される可能性があります。&lt;/p&gt;&#10;&lt;p&gt;ただし、古いプラグインやテーマには、セキュリティなどの観点で別の問題を抱えていることにも留意すべきです。&lt;/p&gt;&#10;&lt;h3 id="学習曲線"&gt;学習曲線&#10;&lt;/h3&gt;&lt;p&gt;最後に、長年にわたりWordPressを使用してきたユーザーの中には、クラシックエディタの使いやすさと見覚えのあるインターフェースのほうが好ましいを感じられる人もいるでしょう。新しいシステムを学ぶことなく、すぐに編集作業を開始できることは、継続的にコンテンツを提供するために重要な要素です。&lt;/p&gt;&#10;&lt;h2 id="新規参加者にとってなぜgutenbergがおすすめなのか"&gt;新規参加者にとって、なぜGutenbergがおすすめなのか&#10;&lt;/h2&gt;&lt;p&gt;これらの理由にもかかわらず、新規のWordPressユーザーに対しては、まずGutenbergを試すことをお勧めします。その理由は、Gutenbergが現在のデフォルトのエディタであり、今後のアップデートと新機能のサポートが続くと考えられるからです。&lt;/p&gt;&#10;&lt;p&gt;GutenbergはWordPressの未来のデザインと機能の方向性を示しています。ブロックベースの設計は、編集体験をより直感的で視覚的にするだけでなく、柔軟性と拡張性も提供します。ユーザーは個々のブロックを使ってページを自由に設計し、各ブロックを個別にカスタマイズすることができます。&lt;/p&gt;&#10;&lt;p&gt;さらに、新機能や改善はまずGutenbergに導入され、新しいテーマやプラグインはGutenbergとの互換性を保証する傾向があります。これは、Gutenbergを学ぶことが、最新のWordPress機能を活用するための重要なステップであることを示しています。&lt;/p&gt;&#10;&lt;h2 id="最終的な選択はユーザーのニーズによる"&gt;最終的な選択はユーザーのニーズによる&#10;&lt;/h2&gt;&lt;p&gt;最終的には、どのエディタを選ぶべきかは、その人が何を求めているか、どのようなスキルや経験を持っているかによります。したがって、最適なエディタを見つけるためには、両方のエディタを試し、自分のニーズと作業フローに最も適しているものを選ぶことをお勧めします。&lt;/p&gt;&#10;&lt;p&gt;しかし、今後のことを考えると、新規のWordPressユーザーは、まずGutenbergを試すことを強くお勧めします。現在のデフォルトのエディタとして、そしてWordPressの未来のデザインと機能の方向性を示しているためです。クラシックエディタはまだ有効な選択肢であり続けますが、新しいユーザーはGutenbergに触れ、その機能と可能性を試すことで、最新のWordPress機能を最大限に活用するための基盤を築くことができます。&lt;/p&gt;&#10;&lt;h2 id="寸評"&gt;寸評&#10;&lt;/h2&gt;&lt;p&gt;僕はクラシックエディタとGutenbergの両方を使っている。このChatGPT-4の回答は、概ね悪くないものだと思う（まぁそのように誘導したとも言えるが…）。&lt;/p&gt;&#10;&lt;p&gt;以下のような質問をした。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;WordPressのGutenbergはクラシックエディタと比べた時、すべての人にとって推奨されるエディタだと言えるか。&lt;/li&gt;&#10;&lt;li&gt;シンプルな編集体験を求めるのは、具体的にどんな人か&lt;/li&gt;&#10;&lt;li&gt;私自身、Gutenbergをメインで使っているブログとクラシックエディタをメインで使っているブログに分かれている。テキストベースのブログでクラシックエディタを今も使っており、実際、機能的にもクラシックエディタのほうが優れていると感じることが多い。Gutenbergではタブキーで箇条書きのインデントを下げるといった、通常テキストエディタに期待されるような機能もなかったりする。 2つの形式をサポートするのはWordPressにとっても負荷が大きいと思うが、実際的に両方に向き不向きがあると感じる。Gutenbergに統一されることはあるのだろうか。&lt;/li&gt;&#10;&lt;li&gt;これからWordPressを始めようという人に、あえてクラシックエディタを勧める理由はあるだろうか。それとも、たとえテキストベースのブログであったとしても、今後のことを考えると、総合的にGutenbergを勧めるべきか。&lt;/li&gt;&#10;&lt;li&gt;ここまでの話を、長くなってもよいのでしっかりとした記事としてまとめてください。特に、今でもクラシックエディタがなくならない理由には必ず触れてください。そのうえでなお、新規参加者はまずGutenbergに触れたほうがよいのは何故かについても書いてください。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;ポイントとして、最初の質問で「すべての」という修飾を入れた。普通に聞けばChatGPT-4がGutenbergを勧めるのは明らかだったからだ。しかし、ChatGPTは「すべて」について語ることを避ける。そこで、「すべての人に勧められるか」を聞いて、勧められないパターンについて言及させた感じだ。&lt;/p&gt;&#10;&lt;p&gt;まぁ、僕自身もこれから始める人がわざわざクラシックエディタから選ぶ必要はないかなと思う。とはいえ、クラシックエディタで既にサイトを運営していてかつ、テキスト主体のブログの人が、あえてGutenbergに乗り換える理由も薄いだろう。&lt;/p&gt;&#10;</description></item></channel></rss>