0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

`ls -l` の結果に MD5ハッシュ値を合体させた「md5ls」コマンドを作ってみた

0
Posted at

はじめに

Linuxでファイルの整合性を確認する際、ls -l でサイズや更新日時を確認し、別途 md5sum でハッシュ値を確認するのが面倒だと感じたことはありませんか?

ls -l のリスト表示の左側に、MD5ハッシュ値が並んでいたら便利なのに……」

そう思い立ち、ls コマンドの結果と md5sum コマンドの結果を合体させた「md5ls」というシェル関数を作成しました。
意外と泥臭い調整(表示ズレ、ディレクトリ判定、隠しファイル対応など)が必要だったので、その完成形を共有します。

完成した「md5ls」コマンド

以下のコードを ~/.bashrc に追記することで使用できます。

my_md5ls_command
md5ls() {
    # サブシェル (...) を使うことで、cd しても元の場所には影響を与えない
    (
        target_dir=""
        opts=() # オプション用配列

        # 引数解析: ディレクトリとそれ以外(オプション)に分ける
        for arg in "$@"; do
            if [ -d "$arg" ]; then
                target_dir="$arg"
            else
                opts+=("$arg")
            fi
        done

        # ディレクトリ指定があった場合はそこに移動
        # (移動しないと隠しファイルや別ディレクトリのファイルを正しくmd5sumできないため)
        if [ -n "$target_dir" ]; then
            cd "$target_dir" || return
        fi

        # --- コマンド生成 ---
        # 配列が空の場合に "" を渡さないように分岐する
        if [ ${#opts[@]} -eq 0 ]; then
            # --group-directories-first でディレクトリを先にまとめて表示
            ls_cmd="ls -al --group-directories-first"
        else
            # オプションがある場合のみ展開して渡す
            ls_cmd="ls -al --group-directories-first \"${opts[@]}\""
        fi

        # ls の実行と md5sum の計算
        # LANG=C を指定して日付フォーマットとエラーメッセージを英語に統一
        eval "LANG=C $ls_cmd" | awk '
        NR==1 { print; next }
        {
            # --- ファイル名の抽出 ---
            # 9列目以降を全て結合してファイル名とする(スペース入りファイル名対応)
            fn=""
            for(i=9;i<=NF;i++) fn = fn (i==9?"":" ") $i

            # --- md5sum の実行 ---
            # ファイル名のエスケープ処理(ダブルクォート対策)
            safe_fn = fn
            gsub(/"/, "\\\"", safe_fn)

            # エラー出力(2>&1)も標準出力として受け取る
            # ここでも LANG=C を指定して "Is a directory" を確実に検出する
            cmd = "LANG=C md5sum \"" safe_fn "\" 2>&1"

            if ((cmd | getline line) > 0) {
                # ディレクトリの場合は固定メッセージを表示してレイアウト崩れを防ぐ
                if (line ~ /Is a directory/) {
                    result_str = "md5sum: Is a directory"
                } else {
                    # 正常な場合はハッシュ値(空白区切りの先頭)のみ抽出
                    split(line, arr, " ")
                    result_str = arr[1]
                    
                    # 万が一エラー文字列だけが返ってきた場合の対策
                    if (result_str == "md5sum:") result_str = "Error"
                }
            } else {
                result_str = "Error"
            }
            close(cmd)

            # --- 表示 ---
            # %-34s で34文字分の幅を確保して左詰めにする
            printf "%-34s %s\n", result_str, $0
        }'
    )
}

設定を反映させます。

source ~/.bashrc

実行結果

コマンド md5ls を実行すると、左側にMD5ハッシュ、右側に ls -al の結果が表示されます。

実行例
$ md5ls
total 1904
md5sum: Is a directory             drwxr-xr-x  2 user01 user01    4096 Feb 16 18:59 .
md5sum: Is a directory             drwxr-xr-x 13 user01 user01    4096 Feb 16 18:38 ..
0f4e36e42809603f5115b381ed98e250   -rwxr-xr-x  1 user01 user01     577 Feb 16 18:37 buff-cache.sh
b07e4809d2188a128a8329385c59353b   -rwxr-xr-x  1 user01 user01    1045 Feb 16 18:37 capture.sh
f7a0fbeb7a3b6cd9af998aeb6dbd82c7   -rwxr-xr-x  1 user01 user01    1028 Feb 16 18:37 demand-paging.py
...

ディレクトリを指定しても動作します(隠しファイルも対応)。

ディレクトリ指定の例
$ md5ls ~/
total 148
md5sum: Is a directory             drwxr-x--- 19 user01 user01  4096 Feb 18 11:52 .
md5sum: Is a directory             drwxr-xr-x  3 root   root    4096 Feb 15 16:43 ..
b9a556fd432880e5ad928f41f42f2608   -rw-------  1 user01 user01 17025 Feb 17 22:32 .bash_history
...

こだわったポイント・技術的な解説

1. ディレクトリの表示崩れ対策

単純に md5sum をディレクトリに対して実行すると、エラーメッセージにディレクトリ名が含まれてしまい、リストの列がガタガタにずれてしまいます。

  • 対策: md5sum の結果に "Is a directory" が含まれる場合は、強制的に "md5sum: Is a directory" という固定長の文字列に置き換えました。
  • 工夫: LANG=C を付与することで、日本語環境でも確実に "Is a directory" という英語メッセージが出力されるようにしています。

2. --group-directories-first の採用

ハッシュ値が表示される「ファイル」と、エラーメッセージが表示される「ディレクトリ」が混ざると見づらいため、ls--group-directories-first オプションを追加しました。これにより、ディレクトリが上部にまとまり、視認性が向上しました。

3. 別ディレクトリの隠しファイル対応

md5ls ~/ のようにパスを指定した際、単純に ls の結果を md5sum に渡すと「ファイルが見つからない」というエラーになります(ls はファイル名だけを返すため)。

  • 対策: サブシェル ( ... ) 内で一時的にターゲットディレクトリへ cd してから処理を行うようにしました。これにより、相対パスの問題を解決しつつ、ユーザーのカレントディレクトリには影響を与えません。

4. レイアウトの整形

awkprintf "%-34s %s\n" を使用しています。MD5ハッシュ値は32文字なので、スペース2文字分を加えて34文字幅で左詰めすることで、右側の ls の結果がきれいに縦に並ぶようにしています。

おわりに

既存の md5deep などのツールもありますが、「いつもの ls -l の見た目のままハッシュを知りたい」というニッチな要望を叶えるには、シェル関数を自作するのが一番でした。

普段の作業で、ファイルの整合性をサッと確認したい時に役立てば幸いです。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?