はじめに

こんにちは!今回はdirnameコマンドについて解説します。

dirnameはファイルパスからディレクトリパス部分だけを抽出するコマンドです。先ほど解説したbasenameの逆バージョンって感じですね。

シェルスクリプトでパスを処理する時に、basenameとセットで超よく使われるコマンドです!

dirnameコマンドとは

dirnameは、フルパスやファイルパスからディレクトリパスの部分だけを取り出す外部コマンドです。

例えば、/home/user/documents/file.txtというパスが与えられたとき、dirname/home/user/documentsだけを抽出します。ファイルのディレクトリパスだけが必要な場合に重宝するコマンドです。

基本構文

1
dirname パス

パスはファイルやディレクトリのパスです。

主なオプション

オプション 説明
-z 出力をNUL文字で区切る(GNU拡張)

使用例

例1: 基本的なパスからディレクトリを抽出

1
dirname /home/user/documents/file.txt

実行結果:

1
/home/user/documents

フルパスから/home/user/documentsというディレクトリパスだけを取り出します。これが基本的な使い方です。

例2: 相対パスでの利用

1
dirname ./documents/file.txt

実行結果:

1
./documents

相対パスでも同じようにディレクトリパスだけを抽出できます。

例3: ファイル名だけが与えられた場合

1
dirname file.txt

実行結果:

1
.

ディレクトリ情報がない場合は、カレントディレクトリを意味する.を返します。

例4: ルートディレクトリの場合

1
dirname /etc/passwd

実行結果:

1
/etc

ルートに近いパスでも正しくディレクトリを抽出します。

例5: スラッシュで終わるパス

1
dirname /home/user/documents/

実行結果:

1
/home/user

パスがスラッシュで終わっていても正しく処理されます。

例6: スクリプト内での利用

1
2
3
4
#!/bin/bash
file="/home/user/projects/app/main.sh"
dir=$(dirname "$file")
echo "ディレクトリは: $dir"

実行結果:

1
ディレクトリは: /home/user/projects/app

スクリプト内で変数に結果を格納して使用できます。

例7: ダブルスラッシュの処理

1
dirname /home//user/documents/file.txt

実行結果:

1
/home//user/documents

複数のスラッシュがあっても、そのまま処理されます。

例8: パイプでの利用

1
echo "/var/log/system.log" | xargs dirname

実行結果:

1
/var/log

他のコマンドと組み合わせて使用できます。

例9: basename と組み合わせ

1
2
3
4
full_path="/home/user/config.ini"
dir=$(dirname "$full_path")
file=$(basename "$full_path")
echo "ディレクトリ: $dir / ファイル: $file"

実行結果:

1
ディレクトリ: /home/user / ファイル: config.ini

dirnamebasenameを組み合わせてパスを分解できます。

例10: 複雑なパスの処理

1
dirname /home/user/./documents/../projects/file.txt

実行結果:

1
/home/user/./documents/../projects

./../を含むパスでも、そのまま処理されます。

Tips・注意点

basename コマンドとセット

dirnamebasenameと逆の処理をします。パスを分解する時は両方を組み合わせるのが定番です。

1
2
3
4
5
6
7
# dirname: ディレクトリを抽出
dirname /home/user/file.txt
# 結果: /home/user

# basename: ファイル名を抽出
basename /home/user/file.txt
# 結果: file.txt

パス正規化には非対応

dirname./../を含むパスをそのまま処理します。正規化(相対パスの解決)には対応していません。

1
2
3
# これは "../documents" が含まれたまま返される
dirname /home/user/./documents/../file.txt
# 結果: /home/user/./documents/..

正規化したい場合はrealpathコマンドを使いましょう。

連続実行で1つ上のディレクトリを取得

1
2
3
dir="/home/user/documents/projects"
parent=$(dirname "$dir")
echo "$parent"   # 結果: /home/user/documents

dirnameを連続実行することで、複数階層上のディレクトリを取得できます。

実践的な使い方

スクリプトの配置ディレクトリを取得

1
2
3
4
#!/bin/bash
# スクリプト自身の配置ディレクトリを取得
script_dir=$(dirname "$(readlink -f "$0")")
echo "スクリプトの位置: $script_dir"

スクリプトがどのディレクトリに配置されているか取得する時に便利です。

ファイルを同じディレクトリにコピー

1
2
3
4
source_file="/home/user/documents/report.pdf"
target_file="/backup/report_new.pdf"
dir=$(dirname "$source_file")
cp "$target_file" "$dir/report_new.pdf"

別の場所にあるファイルを、元ファイルと同じディレクトリにコピーする時に使えます。

ログファイルを出力ディレクトリに配置

1
2
3
4
5
#!/bin/bash
input_file="$1"
output_dir=$(dirname "$input_file")
logfile="$output_dir/process.log"
echo "ログを出力: $logfile"

入力ファイルと同じディレクトリにログファイルを出力する例です。

まとめ

dirnameコマンドのポイント:

  • ファイルパスからディレクトリパスだけを抽出する基本コマンド
  • basenameと組み合わせてパスを分解できる
  • スクリプト内で$(dirname パス)として使用できる
  • ファイル名だけが与えられた場合は.を返す
  • パス正規化には対応していない
  • よく使う組み合わせ: dirname "$file"dirname "$(readlink -f "$0")"

シェルスクリプトを書くなら、dirnamebasenameは必須セットですよ!