PHPでファイルをコピーする方法について

採用はこちら

目次

PHPでファイルをコピーする基本的な方法

PHPでファイルをコピーする場合は、標準関数のcopy()を使用するのが基本です。

copy()を使えば、テキストファイル、画像、CSV、PDF、ZIPなど、さまざまなファイルを別の場所へ複製できます。

基本構文は次のとおりです。

copy(コピー元のファイル, コピー先のファイル);

たとえば、sample.txtsample_copy.txtという名前でコピーする場合は、次のように記述します。

<?php

copy('sample.txt', 'sample_copy.txt');

正常に処理されると、元のsample.txtを残したまま、同じ内容を持つsample_copy.txtが作成されます。

copy関数の基本構文

copy()の基本的な書式は次のとおりです。

copy(
    string $from,
    string $to,
    ?resource $context = null
): bool

主に使用する引数は、$from$toです。

それぞれの意味は次のとおりです。

  • $from:コピー元となるファイルのパス
  • $to:コピー先となるファイルのパス
  • $context:必要に応じて使用するストリームコンテキスト
  • 戻り値:成功した場合はtrue、失敗した場合はfalse

通常のローカルファイルをコピーするだけであれば、第3引数を指定する必要はありません。

コピーの成功と失敗を判定する

実際のプログラムでは、単純にcopy()を実行するだけではなく、戻り値を確認するのがおすすめです。

<?php

$source = 'sample.txt';
$destination = 'sample_copy.txt';

if (copy($source, $destination)) {
    echo 'ファイルをコピーしました。';
} else {
    echo 'ファイルのコピーに失敗しました。';
}

コピーが正常に完了するとtrueが返されるため、if文を使って成功時と失敗時の処理を分けられます。

PHPで別のディレクトリへファイルをコピーする方法

copy()では、ファイル名だけでなくディレクトリを含むパスを指定できます。

そのため、ファイルを別のディレクトリへコピーすることも可能です。

コピー先のディレクトリを指定する

たとえば、次のようなディレクトリ構成があるとします。

project/
├── files/
│   └── sample.txt
└── backup/

filesディレクトリにあるsample.txtbackupディレクトリへコピーする場合は、次のように記述します。

<?php

$source = 'files/sample.txt';
$destination = 'backup/sample.txt';

if (copy($source, $destination)) {
    echo 'ファイルをコピーしました。';
} else {
    echo 'ファイルのコピーに失敗しました。';
}

コピーに成功すると、次のような状態になります。

project/
├── files/
│   └── sample.txt
└── backup/
    └── sample.txt

コピー元のファイルは削除されません。

copyとファイル移動の違い

copy()は、元ファイルを残したまま別のファイルを作成する関数です。

copy('files/sample.txt', 'backup/sample.txt');

処理後は、次の2つのファイルが存在します。

files/sample.txt
backup/sample.txt

一方、元ファイルを残さず別の場所へ移動したい場合は、rename()を利用できます。

rename('files/sample.txt', 'backup/sample.txt');

基本的な使い分けは次のとおりです。

ファイルを複製する → copy()
ファイルを移動する → rename()
ファイル名を変更する → rename()

PHPでファイル名を変更しながらコピーする方法

copy()では、コピー先に別のファイル名を指定できます。

そのため、ファイルをコピーすると同時に名前を変更できます。

コピー先に別のファイル名を指定する

たとえば、sample.txtbackup.txtとしてコピーする場合は次のように記述します。

<?php

$source = 'sample.txt';
$destination = 'backup.txt';

if (copy($source, $destination)) {
    echo 'ファイルをコピーしました。';
}

コピー元は、

sample.txt

ですが、コピー先では、

backup.txt

という名前になります。

バックアップファイルを作成するときなどに便利です。

日付や時刻をファイル名に付ける

バックアップを複数世代保存したい場合は、ファイル名に日時を付ける方法があります。

<?php

$source = 'data.csv';
$destination = 'backup/data_' . date('Ymd_His') . '.csv';

if (copy($source, $destination)) {
    echo 'バックアップを作成しました。';
}

たとえば、2026年8月11日19時50分00秒に処理した場合は、次のようなファイル名になります。

data_20260811_195000.csv

日時を付けることで、既存のバックアップを上書きしにくくなります。

ただし、同じ秒に複数回処理される可能性があるシステムでは、日時だけではファイル名が重複する場合があります。

必要に応じてランダム文字列や一意なIDを追加すると、より安全です。

コピー元のファイルが存在するか確認する方法

コピー元のファイルが存在しない場合、copy()は正常に処理できません。

そのため、事前にファイルが存在するか確認しておくと、エラー処理がしやすくなります。

is_file関数でファイルを確認する

通常のファイルをコピーする場合は、is_file()を使って確認する方法があります。

<?php

$source = 'sample.txt';
$destination = 'backup/sample.txt';

if (!is_file($source)) {
    exit('コピー元のファイルが存在しません。');
}

if (copy($source, $destination)) {
    echo 'ファイルをコピーしました。';
} else {
    echo 'ファイルのコピーに失敗しました。';
}

is_file()は、指定したパスが通常のファイルであるかどうかを確認できます。

file_existsとの違い

file_exists()を使用することもできます。

if (file_exists($source)) {
    copy($source, $destination);
}

ただし、file_exists()はファイルだけでなくディレクトリの存在確認にも使用されます。

コピー元が通常のファイルであることを確認したい場合は、is_file()のほうが目的を明確にできます。

コピー先のディレクトリが存在しない場合

copy()は、存在しないコピー先ディレクトリを自動的に作成してくれるわけではありません。

そのため、コピー先のディレクトリが存在しない場合は、あらかじめ作成する必要があります。

mkdir関数でディレクトリを作成する

次のようにis_dir()mkdir()を組み合わせることができます。

<?php

$source = 'sample.txt';
$directory = 'backup';
$destination = $directory . '/sample.txt';

if (!is_dir($directory)) {
    if (!mkdir($directory, 0755, true)) {
        exit('コピー先ディレクトリを作成できませんでした。');
    }
}

if (copy($source, $destination)) {
    echo 'ファイルをコピーしました。';
} else {
    echo 'ファイルのコピーに失敗しました。';
}

mkdir()の第3引数にtrueを指定すると、必要に応じて親ディレクトリも再帰的に作成できます。

0755を指定するときの注意点

次のように0755を指定することがあります。

mkdir($directory, 0755, true);

ただし、UnixやLinux系の環境では、最終的なパーミッションはumaskの影響を受けます。

そのため、必ずしも指定した値がそのまま設定されるとは限りません。

また、Windowsではpermissions引数の扱いがUnix系OSとは異なります。

ファイルやディレクトリの権限については、実行環境に合わせて確認する必要があります。

コピー先に同名ファイルが存在する場合

copy()を使用するときに注意したいのが、コピー先に同じ名前のファイルが存在するケースです。

既存ファイルは上書きされる

たとえば次の処理を実行するとします。

copy('sample.txt', 'backup/sample.txt');

すでに、

backup/sample.txt

が存在する場合は、基本的に既存ファイルが上書きされます。

そのため、上書きしたくない場合は事前確認が必要です。

<?php

$source = 'sample.txt';
$destination = 'backup/sample.txt';

if (file_exists($destination)) {
    exit('コピー先のファイルはすでに存在します。');
}

if (copy($source, $destination)) {
    echo 'ファイルをコピーしました。';
}

重要なファイルを扱うシステムでは、意図しない上書きを防ぐ仕組みを用意したほうが安全です。

ファイル名を変更して上書きを防ぐ

バックアップ目的であれば、日時を付けたファイル名にする方法があります。

<?php

$source = 'sample.txt';

$destination =
    'backup/sample_' .
    date('Ymd_His') .
    '.txt';

if (copy($source, $destination)) {
    echo 'バックアップを作成しました。';
}

たとえば、次のようなファイルを複数保存できます。

sample_20260811_190000.txt
sample_20260811_193000.txt
sample_20260811_200000.txt

複数世代のバックアップを管理したい場合に便利です。

PHPで絶対パスを使ってファイルをコピーする方法

相対パスでもcopy()は利用できますが、Webアプリケーションでは絶対パスを使ったほうが分かりやすいケースがあります。

__DIR__を使用する

PHPには、現在のPHPファイルが存在するディレクトリを取得できる__DIR__というマジック定数があります。

<?php

$source = __DIR__ . '/files/sample.txt';
$destination = __DIR__ . '/backup/sample.txt';

if (copy($source, $destination)) {
    echo 'ファイルをコピーしました。';
}

たとえばPHPファイルが、

/var/www/html/project/index.php

に存在する場合、__DIR__は概ね次のパスを表します。

/var/www/html/project

そのため、

__DIR__ . '/files/sample.txt'

と記述すれば、PHPファイルが置かれているディレクトリを基準にパスを組み立てられます。

相対パスの解釈によるトラブルを減らしたい場合に便利です。

PHPで画像ファイルをコピーする方法

copy()はテキストファイルだけでなく、画像ファイルにも使用できます。

JPEG画像をコピーする

たとえば、JPEG画像をバックアップディレクトリへコピーする場合は次のように記述します。

<?php

$source = 'images/photo.jpg';
$destination = 'backup/photo.jpg';

if (copy($source, $destination)) {
    echo '画像をコピーしました。';
} else {
    echo '画像のコピーに失敗しました。';
}

copy()では、PHP側で画像の内容を解析する必要はありません。

JPEGだけでなく、PNG、GIF、WebP、PDF、CSV、ZIPなど、さまざまなファイルに利用できます。

ストリームを使ってファイルをコピーする方法

単純なファイルコピーであればcopy()で十分ですが、ストリームを直接扱いたい場合にはstream_copy_to_stream()を利用できます。

stream_copy_to_streamの使い方

基本的なコードは次のとおりです。

<?php

$source = fopen('sample.txt', 'rb');
$destination = fopen('sample_copy.txt', 'wb');

if ($source === false) {
    exit('コピー元ファイルを開けませんでした。');
}

if ($destination === false) {
    fclose($source);
    exit('コピー先ファイルを開けませんでした。');
}

$result = stream_copy_to_stream($source, $destination);

fclose($source);
fclose($destination);

if ($result === false) {
    echo 'コピーに失敗しました。';
} else {
    echo $result . 'バイトコピーしました。';
}

stream_copy_to_stream()は、コピーに成功するとコピーしたバイト数を返します。

失敗した場合はfalseを返します。

copyとの使い分け

一般的なファイルコピーでは、次のように考えると分かりやすいでしょう。

単純にファイルを複製する
→ copy()

ストリームとしてデータを扱う
→ stream_copy_to_stream()

特別な理由がなければ、通常のファイルコピーではcopy()のほうが簡潔です。

URLからファイルをコピーする方法

PHPでは、利用可能なストリームラッパーやPHPの設定によっては、URLをコピー元として扱える場合があります。

URLをコピー元として指定する

たとえば、環境によっては次のような処理が可能です。

<?php

$url = 'https://example.com/image.jpg';
$destination = 'images/image.jpg';

if (copy($url, $destination)) {
    echo 'ファイルを保存しました。';
} else {
    echo 'ファイルを保存できませんでした。';
}

ただし、URLを利用したコピーが必ず利用できるとは限りません。

PHPの設定や使用するストリームラッパー、サーバー環境などによって動作が異なる可能性があります。

また、外部ファイルを取得する場合は、通信エラー、タイムアウト、ファイルサイズ、取得元の信頼性なども考慮する必要があります。

ユーザー入力をURLとして使用するときの注意点

ユーザーが入力したURLをそのままcopy()へ渡すのは危険です。

$url = $_POST['url'];

copy($url, 'download/file.dat');

このような実装では、サーバーから意図しない内部アドレスへアクセスされるSSRFなどのセキュリティリスクが生じる可能性があります。

ユーザー入力を使用する場合は、アクセス可能なドメインを制限するなど、適切な検証が必要です。

PHPでファイルをコピーできない主な原因

copy()が失敗する場合には、いくつかの原因が考えられます。

コピー元のファイルが存在しない

コピー元に指定したファイルが存在しなければ、正常にコピーできません。

if (!is_file($source)) {
    exit('コピー元ファイルが存在しません。');
}

パスの指定ミスもあわせて確認しましょう。

コピー先ディレクトリが存在しない

コピー先の親ディレクトリが存在しない場合も、コピーできません。

必要に応じてmkdir()で作成します。

if (!is_dir($directory)) {
    mkdir($directory, 0755, true);
}

書き込み権限がない

コピー先ディレクトリに書き込み権限がない場合も、コピーに失敗します。

Linux系サーバーでは、次のような項目を確認する必要があります。

  • ファイルやディレクトリの所有者
  • グループ
  • パーミッション
  • Webサーバーの実行ユーザー
  • PHP-FPMの実行ユーザー

単純にパーミッションを広く設定するのではなく、必要なユーザーに必要な権限だけを与えることが重要です。

ファイルパスが間違っている

相対パスを使用している場合、想定とは異なる場所を参照していることがあります。

そのような場合は、__DIR__を使って絶対パスに近い形で指定すると原因を把握しやすくなります。

$source = __DIR__ . '/files/sample.txt';

copy関数とrename関数の違い

PHPでファイルを扱う場合は、copy()rename()の違いを理解しておくことが重要です。

copyは元ファイルを残す

copy()はファイルを複製します。

copy('sample.txt', 'backup/sample.txt');

処理後は、

sample.txt
backup/sample.txt

の両方が存在します。

renameは移動や名前変更に使う

ファイルを移動したい場合は、rename()を利用できます。

rename('sample.txt', 'backup/sample.txt');

また、同じディレクトリ内で名前を変更することもできます。

rename('sample.txt', 'sample_old.txt');

用途に応じて使い分けましょう。

コピーする → copy()
移動する → rename()
名前を変更する → rename()

PHPでファイルをコピーする実用的なサンプル

実際のWebアプリケーションでは、コピー元の確認やコピー先ディレクトリの作成、上書き防止なども含めて処理すると安全です。

エラーチェックを含めたサンプル

<?php

$source = __DIR__ . '/files/sample.txt';
$backupDir = __DIR__ . '/backup';
$destination = $backupDir . '/sample.txt';

// コピー元を確認
if (!is_file($source)) {
    exit('コピー元のファイルが存在しません。');
}

// コピー先ディレクトリを確認
if (!is_dir($backupDir)) {

    if (!mkdir($backupDir, 0755, true)) {
        exit('コピー先ディレクトリを作成できませんでした。');
    }
}

// 同名ファイルの上書きを防止
if (file_exists($destination)) {
    exit('コピー先ファイルがすでに存在します。');
}

// コピーを実行
if (!copy($source, $destination)) {
    exit('ファイルのコピーに失敗しました。');
}

echo 'ファイルをコピーしました。';

処理の流れは次のとおりです。

コピー元のファイルを確認
↓
コピー先ディレクトリを確認
↓
必要ならディレクトリを作成
↓
コピー先に同名ファイルがないか確認
↓
copy()を実行
↓
成功・失敗を判定

単純なcopy()だけのコードよりも、トラブルが発生したときに原因を特定しやすくなります。

PHPでファイルをコピーするときの注意点

ファイル操作はサーバー上のデータに直接影響するため、パスや権限、安全性について注意する必要があります。

ユーザー入力をそのままファイルパスに使用しない

次のようなコードは避けたほうがよいでしょう。

$file = $_GET['file'];

copy($file, 'backup/' . $file);

ユーザーが自由にファイル名やパスを指定できる状態にすると、想定外のファイルへアクセスされる可能性があります。

特に、../などを利用したディレクトリトラバーサルへの対策が必要です。

ユーザー入力を使用する場合は、許可するファイル名を限定したり、操作可能なディレクトリを固定したりすることが重要です。

エラー抑制演算子を安易に使わない

次のようなコードを見かけることがあります。

@copy($source, $destination);

@を使用すると警告を抑制できますが、コピーできなかった原因を把握しにくくなります。

基本的には、戻り値を確認してエラー処理を行うほうが管理しやすいでしょう。

if (!copy($source, $destination)) {
    // エラー処理
}

本番環境では、必要に応じてerror_log()やログライブラリなどを使用して、サーバー側へエラー内容を記録する方法もあります。

重要なファイルは上書き防止を行う

copy()はコピー先に同名ファイルが存在すると上書きするため、重要なファイルを扱う場合は注意が必要です。

上書きしてよいか事前に確認したり、日時や一意な文字列をファイル名に付加したりすると安全です。

PHPでファイルをコピーする方法のまとめ

PHPでファイルをコピーする場合は、標準関数のcopy()を使用するのが基本です。

最もシンプルな書き方は次のとおりです。

<?php

$source = 'sample.txt';
$destination = 'backup/sample.txt';

if (copy($source, $destination)) {
    echo 'ファイルをコピーしました。';
} else {
    echo 'ファイルのコピーに失敗しました。';
}

copy()は、元ファイルを残したまま新しいファイルを作成します。

一方、ファイルの移動や名前変更を行いたい場合はrename()を利用します。

また、ストリームを直接操作したい場合はstream_copy_to_stream()を使用できます。

実際のWebアプリケーションでは、copy()を実行するだけではなく、コピー元ファイルの存在確認、コピー先ディレクトリの作成、同名ファイルの上書き防止、パーミッションの確認、ユーザー入力の検証なども重要です。

特に外部から受け取ったファイル名やURLを使用する場合は、ディレクトリトラバーサルやSSRFなどのセキュリティリスクにも注意する必要があります。

基本的には、単純なファイルコピーならcopy()、ファイルの移動や名前変更ならrename()、ストリーム単位でデータをコピーしたい場合はstream_copy_to_stream()と使い分けるとよいでしょう。

以上、PHPでファイルをコピーする方法についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次