PR
PR

tarでシンボリックリンクをアーカイブする際にリンク先のディレクトリ・ファイル名を使用する方法

記事内に広告が含まれています。

tarでシンボリックリンクをアーカイブする際、リンク先の「実際のディレクトリ名」でアーカイブを作成する方法を紹介します。

現在のディレクトリ構成

まず、以下のような状況を想定します。

bedrock-serverは、同じディレクトリ内にあるバージョン名の付いたbedrock-server-1.21.80.3へのシンボリックリンクです。

/home/minecraft/bedrock/
├── backup
├── bedrock_script.sh
├── bedrock-server -> ./bedrock-server-1.21.80.3
├── bedrock-server-1.21.71.01
└── bedrock-server-1.21.80.3

問題点:シンボリックリンク名でアーカイブされる

tarコマンドには、シンボリックリンク自体ではなく、それが指し示す先の実データをアーカイブするための-hオプションがありますが、このオプションを使うと一つ問題が起こります。

実際にコマンドを実行して確認してみましょう。

$ tar cfhvz bedrock-server.tar.gz -C ../bedrock ./bedrock-server
./bedrock-server/
./bedrock-server/permissions.json
... (中略) ...
./bedrock-server/bedrock_server

bedrock-server.tar.gzというファイルが作成されました。

$ ls -l
total 62488
-rw-rw-r-- 1 minecraft minecraft 63981431 Jun 20 10:32 bedrock-server.tar.gz

作成されたアーカイブを展開してみます。

$ tar xfzv bedrock-server.tar.gz 
./bedrock-server/
./bedrock-server/permissions.json
... (中略) ...
./bedrock-server/bedrock_server

tarコマンドで指定したシンボリックリンク名である「bedrock-server」という名前のディレクトリが展開されました。

$ ls -l
total 62492
drwxrwxr-x 14 minecraft minecraft     4096 Jun 16 23:22 bedrock-server
-rw-rw-r--  1 minecraft minecraft 63981431 Jun 20 10:32 bedrock-server.tar.gz

ディレクトリ内を確認するとリンク先のデータがアーカイブされていることが確認できます。

$ ls -l bedrock-server | head -n 5
total 175300
-rw-rw-r--  1 minecraft minecraft       199 Apr 10 11:08 allowlist.json
-rwxrwxr-x  1 minecraft minecraft 179366696 Apr 22 06:45 bedrock_server
-rw-rw-r--  1 minecraft minecraft     28195 Apr 22 06:32 bedrock_server_how_to.html
drwxrwxr-x 58 minecraft minecraft      4096 Apr 22 06:45 behavior_packs

この方法の課題(tarでhオプション使用時)

この方法では、アーカイブのディレクトリ名は常にシンボリックリンク名(この例ではbedrock-server)になります。

これでは、後からアーカイブファイルを見たときに「このアーカイブは、どのディレクトリのものだっけ?」と判別するのが難しくなってしまいます。

解決策:readlinkでリンク先の「実名」を取得する

この課題を解決するため、readlinkというコマンドを使ってリンク先の実際のパスを取得し、その名前でアーカイブを作成するという方法があります。

シンボリックリンク先の絶対パスを取得する(readlink -f)

readlinkコマンドは、シンボリックリンクのリンク先パスを調べるための専門コマンドです。

  • readlink リンク名:リンク先のパスを表示
  • $ readlink bedrock-server
    ./bedrock-server-1.21.80.3
    
  • readlink -f リンク名:リンク先を再帰的に辿ってリンク先の絶対パスを表示
  • $ readlink -f bedrock-server
    /home/minecraft/bedrock/bedrock-server-1.21.80.3
    

今回はアーカイブをするためのスクリプトを作成し、スクリプト内で確実にパスを扱うために、readlink -fを使っていきます。

親ディレクトリと対象ディレクトリ名に分割する (dirname, basename)

readlink -fで取得した絶対パス「/home/minecraft/bedrock/bedrock-server-1.21.80.3」を、dirnameとbasenameというコマンドを使って、tarコマンドで扱いやすいように「親ディレクトリ」と「対象のディレクトリ」の2つに分けます。

  • 親ディレクトリ(dirnameで取得):/home/minecraft/bedrock
  • 対象ディレクトリ(basenameで取得):bedrock-server-1.21.80.3

以下の簡単なテストスクリプト(readlink_test.sh)を作成し、これらの値が正しく取得できるか確認します。

#!/bin/bash

# readlink -f で絶対パスを取得
TARGET_PATH=$(readlink -f /home/minecraft/bedrock/bedrock-server)
echo "取得した絶対パス(TARGET_PATH): ${TARGET_PATH}"

# dirnameで親ディレクトリ部分を取得
PARENT_DIR=$(dirname "${TARGET_PATH}")
echo "親ディレクトリ (PARENT_DIR): ${PARENT_DIR}" 

# basenameでファイル名・ディレクトリ名部分を取得
TARGET_DIR_NAME=$(basename "${TARGET_PATH}")
echo "対象ディレクトリ名 (TARGET_DIR_NAME):  ${TARGET_DIR_NAME}"

スクリプトを実行してみると、以下のように親ディレクトリと対象ディレクトリ名が取得できていることが確認できました。

$ bash readlink_test.sh 
取得した絶対パス(TARGET_PATH): /home/minecraft/bedrock/bedrock-server-1.21.80.3
親ディレクトリ (PARENT_DIR): /home/minecraft/bedrock
対象ディレクトリ名 (TARGET_DIR_NAME):  bedrock-server-1.21.80.3

tarで実際にアーカイブする

次に、このreadlink_test.shをもとにtarでアーカイブを行うスクリプト(archive.sh )を作成します。

#!/bin/bash

# リンク先の絶対パスを取得
TARGET_PATH=$(readlink -f /home/minecraft/bedrock/bedrock-server)

# パスを親ディレクトリと対象ディレクトリ名に分割
PARENT_DIR=$(dirname "${TARGET_PATH}")
TARGET_DIR_NAME=$(basename "${TARGET_PATH}")

# アーカイブの保存先を指定
ARCHIVE_DIR="/home/minecraft/backup"

# tarコマンドを実行
# $(date "+%Y%m%d_%H%M%S")はアーカイブした日時を取得
# -C オプションで移動先のディレクトリを指定し、余計なパスがアーカイブに含まれないようにする
tar cfzv "${ARCHIVE_DIR}/${TARGET_DIR_NAME}_$(date "+%Y%m%d_%H%M%S").tar.gz" -C "${PARENT_DIR}" "${TARGET_DIR_NAME}"

作成したスクリプトを実行します。

$ bash ./archive.sh

結果を確認すると、シンボリックリンクが指していたbedrock-server-1.21.80.3という実際のディレクトリ名でアーカイブが作成されました。

$ ls -l backup/
total 62508
-rw-rw-r-- 1 minecraft minecraft 64005537 Jun 20 16:24 bedrock-server-1.21.80.3_20250620_162435.tar.gz

展開してみても、ディレクトリ名が維持されていることがわかります。

$ cd backup/
$ tar xfz bedrock-server-1.21.80.3_20250620_162435.tar.gz 
$ ls -l
total 62512
drwxrwxr-x 14 minecraft minecraft     4096 Jun 16 23:22 bedrock-server-1.21.80.3
-rw-rw-r--  1 minecraft minecraft 64005537 Jun 20 16:24 bedrock-server-1.21.80.3_20250620_162435.tar.gz

念のために展開したデータも確認してみると、正常にアーカイブされていることが確認できました。

$ ls -l bedrock-server-1.21.80.3 | head -n5
total 175300
-rw-rw-r--  1 minecraft minecraft       199 Apr 10 11:08 allowlist.json
-rwxrwxr-x  1 minecraft minecraft 179366696 Apr 22 06:45 bedrock_server
-rw-rw-r--  1 minecraft minecraft     28195 Apr 22 06:32 bedrock_server_how_to.html
drwxrwxr-x 58 minecraft minecraft      4096 Apr 22 06:45 behavior_packs

これで、どのデータをアーカイブしたのかが一目でわかるようになります。

コメント

タイトルとURLをコピーしました