bashコマンド補完-あなたのパスにすべての猫を見つける!


今日、私はどのように多くのプログラムを終了して下さいcat 私は自分のシステムを持っていた.私は覚えてcat , zcat と同様のプログラムがあるかどうかを知りたい.タブを押すcat を指定するcat .

1 .apropos私の中では、APROPOSはプログラムがどのようなシステムで利用可能かを検索する方法です.検索文字列apropos 任意のregexすることができます.それでapropos 'cat$' 問題を解決すべきです.cat$ '猫'で終わるすべての語を意味します
出力が
STAILQ_CONCAT (3)     - implementations of singly-linked lists, singly-linked tail queues, lists and tail queues
OPENSSL_strlcat (3ssl) - Memory allocation functions
..
bzcat (1)            - decompresses files to stdout
cat (1)              - concatenate files and print on the standard output
fc-cat (1)           - read font information cache files
gencat (1)           - Generate message catalog

明らかに、トップ2はプログラムのように見えません.なぜですapropos その後、それらを返す?
見てみましょうapropos マニュアル
man apropos
# apropos - search the manual page names and descriptions
So apropos 検索man ページ.そして、man 他のものとちょうどプログラムでないページ.
深く掘り、マニュアルを試してみましょうman ページ!
man man
# The table below shows the section numbers of the manual followed by the types of pages they contain.
#       1   Executable programs or shell commands
#       2   System calls (functions provided by the kernel)
#       3   Library calls (functions within program libraries)
#       4   Special files (usually found in /dev)
#       5   File formats and conventions eg /etc/passwd
#       6   Games
#       7   Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7)
#       8   System administration commands (usually only for root)
#       9   Kernel routines [Non standard]

よろしい.私たちはmanページの実行プログラムです.apropos を使用して検索するセクションを制限する方法があります-s フラグ.apropos -s 1 'cat$' すべてのプログラムの名前で終わるcat manページにはエントリがありますが、manページがないプログラムを表示しません.

2 .パス上のすべてのプログラムをリストする
bashがどのプログラムを直接名前と呼ぶかを知る方法ls ) そして、それらの完全な経路によってではなく/usr/bin/ls ) で見ることです$PATH 環境変数.
**全ての実行可能ファイルをパスにリスト**
以下にパス内の実行可能ファイルを一覧表示する小さなbashスニペットがありますpaths.sh )
#!/bin/bash
# The directories in $PATH are separated by ":", so we split by it to get individual directories
for pdir in $(echo "$PATH" | tr ":" "\n")
do
    # We `find` all files in the directory which are executable and print the filename
    find "$pdir" -maxdepth 1 -executable -type f -printf "%f\n"
done

あなたがPythonを好むならば、これは同じもののための小さなPythonプログラムですpaths.py )
from itertools import chain
import os
path_dirs = os.environ['PATH'].split(':') # Split PATH by ':'
print(path_dirs)
all_files = chain(*(os.walk(p) for p in path_dirs)) # Iterable of all files in the directories contained in PATH
is_exec = lambda x : os.access(x, os.X_OK) # Function to check if a filename is executable
execs = chain(*([f for f in fs if is_exec(os.path.join(r,f))] for r,_,fs in all_files))
for x in execs:
    print(x)
bashやPythonスクリプトを実行すると、正しい出力が得られます.
sh paths.sh | grep 'cat$'
python3 paths.py | grep 'cat$'

bash完成!
私は文字を入力した後タブタブを押すと、私は提案のリストを取得します.どのように、bashはそれをしますか?The Bash manual と言うcomplete and compgen 完成を提案するためのビルトイン.compgen 語のリストを使用して補完を生成します.後者は私たちに特に興味がある.compgen -c すべての実行可能ファイルをパスとシェルの組み込みシェル関数に出力します.compgen --help 次のメッセージを出力します.compgen: compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]
Display possible completions depending on the options.
オプションは次のようになります.
  • エイリアス
  • シェルビルド
  • 実行可能コマンド
  • カレントディレクトリのディレクトリ
  • 変数のエクスポート
  • 現在のディレクトリのファイル
  • システムのグループ
  • 保留中のジョブ(バックグラウンド/停止)
  • bashキーワード
  • S :システムサービス
  • ユーザ名
  • V :全てのシェル変数
  • So compgen -c | grep 'cat$' すべての実行可能な終了を与える必要がありますcat .

    エピローグ
    このウサギの穴に飛び込むことで、bashの完成がどのように機能しているか、どのようにaproposが関連するプログラムを見つけたのか、そしてmanページが様々なセクションにどのように構成されているのかを理解してくれました.