はじめに
こんにちは、Nushell プロジェクトへようこそ。このプロジェクトのゴールは、シンプルなコマンドをパイプでつなぎ合わせるというシェルの Unix 哲学を現代の開発スタイルにもちこむことです。
Nu は Bash のような伝統的なシェル、PowerShell などの高度なシェル、関数型プログラミング、システムプログラミングなど、多くの分野からヒントを得ています。しかし Nu は何でもこなせることを目指すのではなく、いくつかのことをうまくこなせることに注力しています。
- モダンな雰囲気をもつ柔軟なクロスプラットフォームシェルを作ること
- データ構造を理解するコマンドラインアプリケーションを組みあわせることができること
- 現代的な CLI アプリケーションが提供する UX をそなえること
Nu になにができるかをみるには、実際に使ってみることが一番です。
ls
コマンドを実行して最初に気づくことは、テキストブロックではなく、構造化されたテーブルデータが返ってくることです。
ls
# => ╭────┬───────────────────────┬──────┬───────────┬─────────────╮
# => │ # │ name │ type │ size │ modified │
# => ├────┼───────────────────────┼──────┼───────────┼─────────────┤
# => │ 0 │ 404.html │ file │ 429 B │ 3 days ago │
# => │ 1 │ CONTRIBUTING.md │ file │ 955 B │ 8 mins ago │
# => │ 2 │ Gemfile │ file │ 1.1 KiB │ 3 days ago │
# => │ 3 │ Gemfile.lock │ file │ 6.9 KiB │ 3 days ago │
# => │ 4 │ LICENSE │ file │ 1.1 KiB │ 3 days ago │
# => │ 5 │ README.md │ file │ 213 B │ 3 days ago │
# => ...
このテーブルはディレクトリの内容を別の方法で表示しているだけではありません。このテーブルを利用するとスプレッドシートと同じように、よりインタラクティブにデータを操作できます。
最初に行うことはテーブルをサイズでソートすることです。これを行うにはls
の出力を取得して、カラムの内容に基づいてテーブルをソートするコマンドに入力します。
ls | sort-by size | reverse
# => ╭────┬───────────────────────┬──────┬───────────┬─────────────╮
# => │ # │ name │ type │ size │ modified │
# => ├────┼───────────────────────┼──────┼───────────┼─────────────┤
# => │ 0 │ Gemfile.lock │ file │ 6.9 KiB │ 3 days ago │
# => │ 1 │ SUMMARY.md │ file │ 3.7 KiB │ 3 days ago │
# => │ 2 │ Gemfile │ file │ 1.1 KiB │ 3 days ago │
# => │ 3 │ LICENSE │ file │ 1.1 KiB │ 3 days ago │
# => │ 4 │ CONTRIBUTING.md │ file │ 955 B │ 9 mins ago │
# => │ 5 │ books.md │ file │ 687 B │ 3 days ago │
# => ...
この作業をおこなうために、ls
にコマンドライン引数を渡していないことがわかります。代わりに、Nu が提供するsort-by
コマンドを利用して、ls
コマンドの出力をソートしています。また、一番大きなファイルを表示するために逆順に並び替えています。
Nu にはテーブルを扱うための多くのコマンドが用意されています。例えば、1 キロバイトを超えるファイルのみを表示するようにls
コマンドの出力をフィルターできます。
ls | where size > 1kb
# => ╭───┬───────────────────┬──────┬─────────┬────────────╮
# => │ # │ name │ type │ size │ modified │
# => ├───┼───────────────────┼──────┼─────────┼────────────┤
# => │ 0 │ Gemfile │ file │ 1.1 KiB │ 3 days ago │
# => │ 1 │ Gemfile.lock │ file │ 6.9 KiB │ 3 days ago │
# => │ 2 │ LICENSE │ file │ 1.1 KiB │ 3 days ago │
# => │ 3 │ SUMMARY.md │ file │ 3.7 KiB │ 3 days ago │
# => ╰───┴───────────────────┴──────┴─────────┴────────────╯
Unix 哲学にあるように、コマンドをつなぎ合わせることで様々な組み合わせを作り出すことができます。別のコマンドをみてみましょう。
ps
# => ╭─────┬───────┬───────┬──────────────────────────────────────────────┬─────────┬───────┬──────────┬──────────╮
# => │ # │ pid │ ppid │ name │ status │ cpu │ mem │ virtual │
# => ├─────┼───────┼───────┼──────────────────────────────────────────────┼─────────┼───────┼──────────┼──────────┤
# => │ 0 │ 87194 │ 1 │ mdworker_shared │ Sleep │ 0.00 │ 25.9 MB │ 418.0 GB │
# => │ 1 │ 87183 │ 2314 │ Arc Helper (Renderer) │ Sleep │ 0.00 │ 59.9 MB │ 1.6 TB │
# => │ 2 │ 87182 │ 2314 │ Arc Helper (Renderer) │ Sleep │ 0.23 │ 224.3 MB │ 1.6 TB │
# => │ 3 │ 87156 │ 87105 │ Code Helper (Plugin) │ Sleep │ 0.00 │ 56.0 MB │ 457.4 GB │
# => ...
もしあなたが Linux を利用しているならps
コマンドには馴染みがあるでしょう。これを使うと、現在システムが実行しているすべてのプロセスの状態や名前の一覧を取得することができます。プロセスの CPU 負荷も確認することができます。
CPU をアクティブに利用しているプロセスを表示したい場合はどうでしょうか。さきほどのls
コマンドと同じように、ps
コマンドが返すテーブルを利用することができます。
ps | where cpu > 5
# => ╭───┬───────┬───────┬─────────────────────────────────────────┬─────────┬───────┬──────────┬──────────╮
# => │ # │ pid │ ppid │ name │ status │ cpu │ mem │ virtual │
# => ├───┼───────┼───────┼─────────────────────────────────────────┼─────────┼───────┼──────────┼──────────┤
# => │ 0 │ 86759 │ 86275 │ nu │ Running │ 6.27 │ 38.7 MB │ 419.7 GB │
# => │ 1 │ 89134 │ 1 │ com.apple.Virtualization.VirtualMachine │ Running │ 23.92 │ 1.5 GB │ 427.3 GB │
# => │ 2 │ 70414 │ 1 │ VTDecoderXPCService │ Sleep │ 19.04 │ 17.5 MB │ 419.7 GB │
# => │ 3 │ 2334 │ 1 │ TrackpadExtension │ Sleep │ 7.47 │ 25.3 MB │ 418.8 GB │
# => │ 4 │ 1205 │ 1 │ iTerm2 │ Sleep │ 11.92 │ 657.2 MB │ 421.7 GB │
# => ╰───┴───────┴───────┴─────────────────────────────────────────┴─────────┴───────┴──────────┴──────────╯
これまで、ls
とps
を利用してファイルやプロセスの一覧を表示しました。Nu はこの他にも便利なテーブルを作り出すコマンドを提供します。次にdate
とsys
をみてみましょう。
date now
を実行すると、現在の日時と時間に関する情報が得られます。
date now
# => 2022-03-07 14:14:51.684619600 -08:00
sys
は Nu が実行されているシステムに関する情報を提供します。
sys
# => ╭───────┬───────────────────╮
# => │ host │ {record 6 fields} │
# => │ cpu │ [table 4 rows] │
# => │ disks │ [table 3 rows] │
# => │ mem │ {record 4 fields} │
# => │ temp │ [table 1 row] │
# => │ net │ [table 4 rows] │
# => ╰───────┴───────────────────╯
これはさきほどまでのテーブルと少し異なります。sys
コマンドは単純な値ではなくセルに構造化されたテーブルを含むテーブルを提供します。このデータを見るには表示する列を選択する必要があります。
sys | get host
# => ╭────────────────┬────────────────────────╮
# => │ name │ Debian GNU/Linux │
# => │ os version │ 11 │
# => │ kernel version │ 5.10.92-v8+ │
# => │ hostname │ lifeless │
# => │ uptime │ 19day 21hr 34min 45sec │
# => │ sessions │ [table 1 row] │
# => ╰────────────────┴────────────────────────╯
get
コマンドを利用するとテーブルのカラムの内容を調べることができます。ここでは、Nu が実行されているホストに関する情報を含む"host"列を調べています。OS の名前、ホスト名、CPU などです。システム上のユーザーの名前を取得してみましょう。
sys | get host.sessions.name
# => ╭───┬──────────╮
# => │ 0 │ sophiajt │
# => ╰───┴──────────╯
現在、システムには"sophia"という名前のユーザが1人だけいます。列の名前だけではなくパスも渡せることに気づくでしょう。Nu はパスを受け取るとテーブルの対応するデータを取得します。
テーブルデータではなく、文字列"sophia"を取得したことに気づかれたかもしれません。Nu はテーブルだけでなく文字列も扱います。文字列は Nu 以外のコマンドを扱う上で重要な役割をはたします。
実際に Nu の外で文字列がどのように機能するか見てみましょう。先ほどの例で外部のecho
コマンドを実行します。(^
は組込みのecho
コマンドを使用しないよう指示しています)。
sys | get host.sessions.name | each { |elt| ^echo $elt }
# => sophiajt
するどい読者にはこれが以前ものと似ていると思われるでしょう。しかし、さきほどの出力でecho
を呼び出しているという重要な違いがあります。このように、Nu からデータをecho
(またはgit
のような Nu 以外の任意のコマンド)にわたすことができるのです。
注:Nu の組み込みコマンドのヘルプテキストは、help
コマンドで検出できます。
help path
# => Explore and manipulate paths.
# =>
# => There are three ways to represent a path:
# =>
# => * As a path literal, e.g., '/home/viking/spam.txt'
# => * As a structured path: a table with 'parent', 'stem', and 'extension' (and
# => * 'prefix' on Windows) columns. This format is produced by the 'path parse'
# => subcommand.
# => * As an inner list of path parts, e.g., '[[ / home viking spam.txt ]]'.
# => Splitting into parts is done by the `path split` command.
# =>
# => All subcommands accept all three variants as an input. Furthermore, the 'path
# => join' subcommand can be used to join the structured path or path parts back into
# => the path literal.
# =>
# => Usage:
# => > path
# =>
# => Subcommands:
# => path basename - Get the final component of a path
# => path dirname - Get the parent directory of a path
# => path exists - Check whether a path exists
# => path expand - Try to expand a path to its absolute form
# => path join - Join a structured path or a list of path parts.
# => path parse - Convert a path into structured data.
# => path relative-to - Get a path as relative to another path.
# => path split - Split a path into parts by a separator.
# => path type - Get the type of the object a path refers to (e.g., file, dir, symlink)
# =>
# => Flags:
# => -h, --help
# => Display this help message