Home About Contact
Bash , Awk , Note Taking

コマンドラインでテキストファイルを作成するときに UUID 付きのファイル名を生成したい

メモを残すときにファイルをコマンドラインでつくるのだがファイル名を考えるのが面倒などの理由により UUID 付きのファイル名にしたい場合がある。 そのやり方の備忘録です。

macOS には uuidgen というコマンドがあり UUID を生成できます。

ChromeOS Linux の場合 sudo apt install uuid-runtime などとするとこのコマンド使えるようになった。

このように:

$ uuidgen
8029FF60-ED12-4DD0-8525-F618C0990BE2

UUID なので当然実行するたびに異なる文字列が生成されます。

好みの問題ですが、大文字というのがいやなので、小文字にします。 さまざまなやり方があるようですが、 Awk を使うのが現在の状況では都合がよさそうなので、そうします。

$ echo `uuidgen` | awk '{print tolower($0)}'
4dacb29d-32ea-4c37-b3b2-0a0781504cb7

この macOS にはあらかじめ Awk はインストールされていた。

$ which awk
/usr/bin/awk

今はテキストファイルをつくりたいので、 txt 拡張子を追加しましょう。

$ echo `uuidgen` | awk '{print tolower($0".txt")}'
7b71d221-a17f-4fa1-bae3-7b7a71b0705f.txt

このファイル名でファイルを生成したいので touch コマンドを併用します。

もし単に UUID のみのファイル名でよければ touch を使って、次のようにします。

$ touch `uuidgen`

しかし今はファイル名を UUID のみではなく小文字にした上で txt の拡張子をつけたい。 この uuidgen の代わりに echo `uuidgen` | awk '{print tolower($0".txt")}' を実行したい。

echo `uuidgen` の部分で既にバッククォートを使っているので、 さらにその外側でバッククォートを使うには、 内側にあるそれをバックスラッシュでエスケープする必要があります。

$ touch `echo \`uuidgen\` | awk '{print tolower($0".txt")}'`

これで機能するにはする。ややこしい。 この問題を解消するには ドル括弧 を使う。 bash には、このバッククォートと同じ役割を果たす ドル括弧 があった。

つまり、次のように書くことができる。

$ touch $(echo `uuidgen` | awk '{print tolower($0".txt")}')

これならバックスラッシュによるエスケープを使わないで済む。

でも、それならば、 同じ機能を実現するために ドル括弧とバッククォートをそれぞれ使うのではなく、 ドル括弧だけ使えばいいじゃないか?

$ touch $(echo $(uuidgen) | awk '{print tolower($0".txt")}')

もちろん、これでよいのですが、個人的には、ドル括弧が二重に入れ子になっているのはすっきりしません。 ここでは、一番外側だけをドル括弧する方式でいくことにします。

これで UUID 付きで txt 拡張子を持つファイルを生成できました。

もし、Vim を使ってメモを書く人であれば:

$ vim $(echo `uuidgen` | awk '{print tolower($0".txt")}')

とする。

さらに改良する

毎回、これだけ長いコマンドをタイプするわけはない。

そこで newtxtfile というコマンドをつくります。

#!/bin/bash
vim $(echo `uuidgen` | awk '{print tolower($0".txt")}')

これを PATH の通った場所に newtxtfile というファイル名で保存して chmod u+x newtxtfile して実行権を付与しておけば、どのディレクトリにいても newtxtfile するだけで、 UUID 付きの txt 拡張子を持ったファイルがカレントディレクトリに生成された上で Vim が起動して 即座にメモを書くことができます。

Vim だけでなく Emacs を使ってメモしたくなったらどうするんだ、という場合は newtxtfile コマンドに vim として 特定エディタコマンドをハードコーディングするのではなく、 echo でファイル名を標準出力するだけに留めておきましょう。

#!/bin/bash
echo $(echo `uuidgen` | awk '{print tolower($0".txt")}')

newtxtfile コマンドをこのようにしておけば Emacs を使いたいときは

$ emacs `newtxtfile`

として Vim を使いたければ

$ vim `newtxtfile`

のようにすればよい。

コマンドラインでタイプして使うにはやはりバッククォートの方がしっくりきます。 慣れの問題かもしれません。 もちろん emacs $(newtxtfile) とドル括弧を使っても構いません。

別に VS Code でも構いません、そうしたければ。(設定しないとなにやら Select a language とかなんとか言われたが。)

$ code `newtxtfile`

まとめ

これで、一つのディレクトリ内にファイル名の重複なしにファイルを作成できる。