はじめに (対象読者・この記事でわかること)

この記事は、サーバー管理者やシステムエンジニア、そして日常的に Linux のファイルシステムを操作する開発者を対象としています。ディレクトリ構造の再編成に伴い、下位にあるすべてのファイル・ディレクトリを上位へ移動しつつ、元の所有者・グループ・パーミッションを正しく引き継ぐ方法がわからない、という方に最適です。この記事を読むことで、mvfindchmodchown を組み合わせた安全な移動手順と、権限引き継ぎのベストプラクティスが身につきます。さらに、実務で遭遇しがちな権限トラブルの事前回避策も紹介します。

前提知識

この記事を読み進める上で、以下の知識があるとスムーズです。

  • 基本的な Linux コマンド(ls, cp, mv, chmod, chown)の操作経験
  • シェルスクリプトの基礎(変数・ループ・条件分岐)が理解できていること

ディレクトリ再編成の背景と概要

システムの運用が長期間にわたると、プロジェクトの要件変更やデータ整理の必要性からディレクトリ構造を見直すことがあります。単に mv コマンドで上位ディレクトリへ移動すれば済むように思えますが、実際には以下のような問題が潜んでいます。

  1. 権限の不整合
    移動先ディレクトリの親が異なる所有者・グループを持つ場合、元のファイルが期待通りにアクセスできなくなる可能性があります。

  2. ACL(アクセス制御リスト)や特殊ビット
    setuidsetgidsticky ビットの継承が適切に行われないと、サービス実行時に権限エラーが発生します。

  3. シンボリックリンクの扱い
    移動時にリンクが壊れるケースが多く、リンク先のパス解決が失敗します。

本稿では、「下層すべてを選択し、権限を引き継いで上位へ安全に移動」 という要件を満たす具体的な手順と、考慮すべきポイントを段階的に解説します。

実践!下層ディレクトリを上位へ移動し権限を引き継ぐ手順

以下のシナリオを想定します。

  • 移動元: /var/www/old_project
  • 移動先: /var/www/new_project (すでに存在し、所有者は www-data:www-data、パーミッションは 755

ステップ1:対象ディレクトリの権限情報を取得

まず、移動対象全体の権限情報を取得し、後で再適用できるように保存します。getfacl がインストールされていない場合は apt-get install acl などでインストールしてください。

Bash
# 移動対象の ACL 情報をファイルに出力 cd /var/www/old_project getfacl -R . > /tmp/old_project_acl.txt

このファイルには、所有者、グループ、モードビット、拡張 ACL がすべて記録されています。

ステップ2:ディレクトリ構造を保持したまま移動

mv コマンドだけだと所有者が変わってしまうことがあります。そこで rsync を利用して属性を保持しつつ移動し、完了後に元ディレクトリを削除します。

Bash
# -a: アーカイブモード(属性・リンク・デバイス等を保持) # --remove-source-files: 移動後に元ファイルを削除 rsync -a --remove-source-files /var/www/old_project/ /var/www/new_project/

※末尾のスラッシュに注意。old_project/ とすることで中身だけがコピーされます。

ステップ3:ACL の再適用

先ほど保存した ACL を新しい場所に適用します。

Bash
cd /var/www/new_project setfacl --restore=/tmp/old_project_acl.txt

setfacl --restore はファイルごとに元の ACL を復元するので、権限のずれを防げます。

ステップ4:所有者・グループの統一

上位ディレクトリの所有者・グループが www-data:www-data であることを前提に、全体の所有者を一括で変更します。findchown を組み合わせると安全です。

Bash
# ディレクトリとファイル両方を対象に所有者を www-data に統一 find /var/www/new_project -exec chown www-data:www-data {} +

ステップ5:パーミッションの最終調整

システム要件に合わせて、特定のディレクトリだけ特殊ビットを設定します。例として setgid を付与し、以後作成されるファイルが自動的に同じグループになるようにします。

Bash
chmod g+s /var/www/new_project/uploads chmod 2775 /var/www/new_project/uploads # setgid + rwxrwxr-x

ハマった点やエラー解決

1. rsync でシンボリックリンクが壊れた

症状: 移動後、リンク先が No such file or directory になる。
原因: デフォルトでは rsync がシンボリックリンクをコピー先にそのまま作成しますが、リンク先が相対パスの場合、元の構造が変わると参照先がずれます。
解決策: -L(リンク先の実体をコピー)または --relative を使用し、リンクの相対パスを保ちます。

Bash
rsync -aL --remove-source-files /var/www/old_project/ /var/www/new_project/

2. setfacl --restore で「Operation not permitted」エラー

症状: ACL の復元時に権限エラーが出る。
原因: 復元対象ファイルが別ユーザーの所有になっているため、現在のユーザーに書き込み権限がない。
解決策: sudo で実行するか、事前に所有者を正しく設定した上で ACL を適用する。

Bash
sudo setfacl --restore=/tmp/old_project_acl.txt

3. find -exec chown が「Argument list too long」になる

症状: 大量のファイルがある場合に Argument list too long が出る。
原因: -exec が一度に多くのパスを渡すため。
解決策: + ではなく \; を使い、1つずつ処理させるか、xargs と組み合わせる。

Bash
find /var/www/new_project -print0 | xargs -0 -n 1000 chown www-data:www-data

完全スクリプト例

以下に、上記手順を自動化したシェルスクリプトを示します。実行前に変数 SRCDEST を目的に合わせて変更してください。

Bash
#!/usr/bin/env bash set -euo pipefail # ----- 設定 ----- SRC="/var/www/old_project" DEST="/var/www/new_project" OWNER="www-data" GROUP="www-data" ACL_BACKUP="/tmp/old_project_acl.txt" # 1. ACL バックアップ echo "バックアップ: $SRC の ACL を取得" cd "$SRC" getfacl -R . > "$ACL_BACKUP" # 2. rsync で属性保持しつつ移動 echo "rsync により $SRC の中身を $DEST に移動" rsync -a --remove-source-files "$SRC"/ "$DEST"/ # 3. ACL の復元 echo "ACL を $DEST に復元" cd "$DEST" setfacl --restore="$ACL_BACKUP" # 4. 所有者・グループ統一 echo "所有者とグループを $OWNER:$GROUP に設定" find . -exec chown "$OWNER":"$GROUP" {} + # 5. 必要な特殊ビット設定(例: uploads ディレクトリ) if [[ -d "./uploads" ]]; then echo "uploads ディレクトリに setgid を設定" chmod g+s ./uploads chmod 2775 ./uploads fi echo "ディレクトリ再構築が完了しました。"

このスクリプトは、「権限を引き継いだまま安全にディレクトリ構造を変更」 するためのフルパイプラインです。実環境でのテストは、必ずバックアップを取得した上で実施してください。

まとめ

本記事では、Linux 環境において下位ディレクトリ全体を上位へ移動し、所有者・グループ・ACL などの権限を正しく引き継ぐ手順を解説しました。

  • ACL の事前取得と復元 によって拡張権限を保持
  • rsync のアーカイブモード で属性・リンク・デバイスを安全に転送
  • find + chownchmod で所有者・特殊ビットを一括調整

これらを組み合わせることで、権限トラブルを未然に防ぎながらディレクトリ構造の再編成が可能になります。次回は、NFS 環境や Docker コンテナ内部で同様の操作を行う際の注意点について取り上げる予定です。

参考資料