Apache

【Apache】Rewriteで別のフォルダの同じファイル名へリダイレクトさせる方法

ApacheのRewriteRuleで、別フォルダの同じファイル名へリダイレクトさせる書き方を紹介します。()の後方参照と$1、R=301やLなどのフラグ、.htaccessとhttpd.confでパターンが変わる理由、RewriteCondで条件を付ける例まで解説します。

この記事の目次
  1. Rewriteで別のフォルダの同じファイル名へリダイレクトさせる
  2. ()グループ化を使ってパスを切り取る
  3. .htaccessではフォルダ名をパターンに含めない
  4. フラグでリダイレクトか内部書き換えかを決める
  5. 条件を付けたいときはRewriteCond
  6. うまく動かないときの確認

ApacheのRewriteで別のフォルダの同じファイル名へリダイレクトさせる方法を紹介します。

結論として、RewriteRuleの書き方は「RewriteRule パターン 置換先 [フラグ]」の3つで決まります。元のパスのうち引き継ぎたい部分を正規表現の()でグループ化し、置換先で$1として受け取れば、subfolder1/page.htmlsubfolder2/page.htmlのように同じファイル名のまま別フォルダへ送れます。ブラウザのURLも変えたい(リダイレクトしたい)ときは[R=301,L]を付け、サーバー内部で差し替えるだけならフラグなしか[L]だけにします。

まずは、後方参照です。

Rewriteで別のフォルダの同じファイル名へリダイレクトさせる

()グループ化を使ってパスを切り取る

()グループ化を使ってパスを切り取ります。
/some-folder/.htaccessに書く場合の例です。

RewriteEngine On
RewriteBase /some-folder/
RewriteRule ^subfolder1/(.+\.html)$ subfolder2/$1 [R=301,L]

パターンの.+\.htmlは、htmlで終わるすべてのファイルという意味になります。
.は任意の一文字を指定します。+は1回以上の繰り返しです。
\.はエスケープして、.を文字列として取り扱っています。
正規表現については、正規表現の基礎を参考にしてみてください。
^$で先頭と末尾を固定しておくと、subfolder1/を含む別のパスに誤ってマッチするのを防げます。

そして、正規表現の部分を()でグループ化します。
そうすると、$1 ~ $9でマッチした文字列が渡ってきます。
それをsubstitution(置換先)の場所で使用できます。
つまり、subfolder1/のあとの()の部分が、subfolder2/の$1の部分に渡ってきます。

.htaccessではフォルダ名をパターンに含めない

.htaccessに書くRewriteRuleは、その.htaccessがあるフォルダまでのパスを取り除いた残りに対してマッチします。/some-folder/.htaccessに置くなら、パターンはsubfolder1/...から書き始め、some-folder/は含めません。
一方、httpd.confVirtualHostに書く場合は/から始まるパス全体がマッチ対象なので、^/some-folder/subfolder1/(.+\.html)$のように先頭の/とフォルダ名まで書きます。
「.htaccessでは効くのにhttpd.confに移したら効かない(またはその逆)」は、たいていこの違いが原因です。
.htaccessが有効になる条件(AllowOverride)はApache .htaccessの書き方と使い方で解説しています。

フラグでリダイレクトか内部書き換えかを決める

フラグ 動作 使いどころ
[R=301,L] ブラウザへ301を返し、URLが置換先に変わる フォルダ移転・恒久的な引っ越し
[R=302,L] 一時的なリダイレクト メンテナンス中の一時退避
[L](Rなし) URLはそのまま、サーバー内部で別ファイルを返す URLを見せたまま実体だけ移したいとき
[NC] 大文字小文字を区別しない Page.HTMLのような表記ゆれを吸収

Lは「このルールでマッチしたら以降のルールを見ない」という意味で、リダイレクトのときはほぼ必ず付けます。
フラグの詳しい意味や複数ルールの組み合わせはRewriteRuleでURLを書き換える方法と意味にまとめています。

条件を付けたいときはRewriteCond

「移転先にファイルが実在するときだけ転送する」のように条件を付けるには、RewriteRuleの直前にRewriteCondを置きます。

RewriteEngine On
RewriteBase /some-folder/
RewriteCond %{DOCUMENT_ROOT}/some-folder/subfolder2/$1 -f
RewriteRule ^subfolder1/(.+\.html)$ subfolder2/$1 [R=301,L]

RewriteCondの変数や条件式の書き方はApache RewriteCondの書き方・使い方を参照してください。

うまく動かないときの確認

  • ブラウザが301をキャッシュしている: シークレットウィンドウか、確認中はR=302で試す
  • ルールが無限に繰り返される: 置換先が同じパターンに再びマッチしていないか確認し、Lを付ける
  • どのルールが効いたか分からない: リライトのログを出す。手順はリライトのログの出力方法と設定方法で解説しています
スポンサーリンク