はじめに
2年前、ユーザーアカウント作成時のパスワード作成のために、ランダムな数字列を生成してクリップボードにコピーするWindowsのバッチファイル(.bat)を作成しました。
@echo off
cd /d "%~dp0"
setlocal enabledelayedexpansion
set "length=4"
set "randomString="
for /L %%i in (1, 1, %length%) do (
set "rand=!RANDOM!"
set "randomString=!randomString!!rand:~-1!"
)
:: 改行を含めずに文字列をクリップボードにコピー
<nul set /p ="!randomString!" | clip
補足:なぜ !randomString!(遅延展開)なのか?
遅延環境変数(setlocal enabledelayedexpansion)を使っている環境では、ループの外であっても %randomString% ではなく !randomString! で出力する方が安全です。バッチファイル特有のパース(解析)エラーを完全に防ぐことができます。
バッチファイルの最後に、利便性を考えて「改行を含めずに文字列をクリップボードにコピー」するコードを入れることを目指しました。
当時は生成AIを使う事も出来ず、ググると出てきたのが、set /p を使う方法です。
しかし、複数の書き方が出てきて、どれが正しいのか悩みました。
現在は、生成AIを使う事が出来るので、よく見かける4つの書き方を比較し、どれが最も安全で、なぜそれがベストなのか を解説してもらいました。
Geminiによる4つの書き方の比較
よく見かける4つの構文を比較した結果がこちらです。
| # | 構文 | 評価 | 理由・解説 |
|---|---|---|---|
| ① | set /P <NUL="!randomString!" | clip |
❌ NG |
構文エラーになります。 set /p の後ろは「変数名=プロンプト」である必要があるため、<NUL が変数名の一部とみなされてしまいます。 |
| ② | echo. | set /p ="!randomString!" | clip |
🔺 微妙 | 動きますが、パイプを2回(多段で)通すため内部的なプロセス起動が多く非効率です。また、echo. は実行のたびにディスクを参照する古い仕様があるため処理が重くなります。 |
| ③ | set /P "=!randomString!" <nul | clip |
◯ 普通 | 動作はしますが、<nul が後ろにあるため、バッチファイルの解析順序(パース)によってはプロンプト(画面に出す文字)の解釈が不安定になることがあります。 |
| ④ | <nul set /p ="!randomString!" | clip |
👑 最適 |
最も安全な標準的スタイル。 リダイレクト(<nul)を先頭に置くことで、後ろの set /p の構文を絶対に邪魔せず、パイプも1回で済むため最もスマートです。 |
最も安全でエラーが起きにくいのは ④番目の書き方 です。
Geminiによる、④番目が最もおすすめな理由
そもそも set /p は、本来 「ユーザーに文字を入力してもらうためのコマンド」 です。
- 本来の構文:
set /p 変数名="画面に表示する文字"
今回は「入力待ち」をさせずに画面表示(文字の出力)だけを行いたいため、「空っぽの入力(nul)をあらかじめ流し込む」 というトリッキーな方法をとっています。
ネットの記事では ③番目(末尾に <nul)の書き方も多く見かけますが、「リダイレクト(<nul)は先頭に置く」 と覚えておくと、構文のバグに悩まされる確率がグッと減ります。
このとき、<nul を先頭に書いておくことで、コマンドプロンプトに対して「これからnulを入力するよ!」と最初に明確に伝えることができます。これにより、後ろのイコールの左側にスペースを空けない特殊な書き方(set /p ="文字列")が誤作動を起こすのを防ぎ、確実にクリップボードへ文字を渡すことができます。
まとめ
バッチファイルで改行なし出力をしたいときは、ぜひ <nul set /p ="!randomString!" | clip を使ってみてください。