scp(secure copy)は、SSH経由でローカルとリモートサーバーの間をファイル転送するコマンドです。書き方はcpとほぼ同じ「scp 元 先」で、リモート側をユーザー@ホスト:パスと書くだけ。FTPソフトを開かなくても、ターミナルからサーバーへのアップロード・ダウンロードが一発で済みます。
ただしscpには、知らないと必ずハマる罠が2つあります。ポート指定がsshと違って大文字の-Pであること(小文字-pは別の意味)、そしてリモート指定のコロン:を忘れると、ホスト名と同じ名前のファイルがローカルにできてしまうことです。この記事では、実際のレンタルサーバー(エックスサーバー)との転送で動作と罠の両方を確認しながら、scpを整理します。
- アップロードは
scp ファイル ユーザー@ホスト:リモートパス、ダウンロードは逆順です。 - ポート指定は大文字
-P(sshの-pと違う)。小文字-pは「日時の保持」です。 - ディレクトリごと転送するには
-rを付けます。 - リモート側の
:を忘れると、ただのローカルコピーになりホスト名のファイルができます。 - 秘密鍵は
-i 鍵ファイルで指定します。 - 大量・繰り返しの転送は
rsyncが向いています(差分転送)。
接続後のファイル編集はSSHでリモートサーバーに接続してファイルを編集する方法、ポート変更をしているサーバーへの接続はSSHポート番号の変更、ローカルのコピー操作はcp・mv・rmもあわせて参考になります。
基本:アップロードとダウンロード
scpの書き方はcpと同じ「元→先」です。リモート側はユーザー@ホスト:パスの形で書きます。コロン:のあとがリモートのパスです。
# ローカル → リモート(アップロード) scp local.txt user@example.com:/home/user/ # リモート → ローカル(ダウンロード) scp user@example.com:/home/user/remote.txt ./ # ダウンロードして名前も変える scp user@example.com:/home/user/remote.txt renamed.txt
実際にレンタルサーバーとの間で確認したところ、ローカルのファイルをアップロードしてリモートでcatすると中身が一致し、そのファイルをダウンロードし直しても内容が完全に往復しました。「元→先」の順はcpと同じなので、アップロードは「ローカルが左」、ダウンロードは「リモートが左」と覚えれば迷いません。リモートパスを:だけにする(user@host:)と、リモートのホームディレクトリに置かれます。
【最重要】ポートは大文字-P(小文字-pの罠)
scp最大の罠がこれです。SSHのポート指定はssh -p 10022のように小文字ですが、scpでは大文字の-Pです。小文字の-pは「タイムスタンプなどを保持する」という別の意味(cp -pと同じ)になります。
# OK: scp のポート指定は大文字 -P scp -P 10022 local.txt user@example.com:/tmp/ # NG: 小文字 -p はポート指定ではない! scp -p 10022 local.txt user@example.com:/tmp/ # → -p は「日時保持」、10022 は「転送するファイル名」と解釈され、 # 既定の22番ポートに接続しに行って失敗する # ssh: connect to host example.com port 22: Connection timed out # 参考: ssh は小文字 -p(紛らわしいので注意) ssh -p 10022 user@example.com
実際にポート10022のサーバーへ小文字-pで転送を試したところ、10022がポートではなく「転送するファイルの1つ」として解釈され、既定の22番ポートへ接続しに行ってssh: connect to host ... port 22: Connection timed outで失敗しました。scpの小文字-pはcp -pと同じ「タイムスタンプ等の保持」です。「sshは小文字・scpは大文字」という非対称は本当に間違えやすいので、ポート変更済みサーバー(エックスサーバーの10022など)にscpするときは-Pを必ず確認してください。「ポートを指定したはずなのにport 22でタイムアウトする」ときは、まずこの大文字小文字を疑うのが近道です。
ディレクトリ転送(-r)と鍵指定(-i)
ディレクトリごと転送するには-rを付けます。また、公開鍵認証のサーバーでは-iで秘密鍵を指定します。
# ディレクトリを丸ごとアップロード scp -r mydir user@example.com:/home/user/backup/ # 秘密鍵を指定して転送(鍵認証のサーバー) scp -i ~/.ssh/id_ed25519 -P 10022 local.txt user@example.com:/tmp/ # オプションはまとめて書ける(順序は パス指定の前) scp -i ~/.ssh/mykey -P 10022 -r mydir user@example.com:/tmp/
実機でも、-rでディレクトリを中のファイルごとアップロードでき、リモート側で中身が正しく読めました。-iはsshと同じ書き方で秘密鍵を指定します。オプションは必ず「元パス・先パス」より前に書いてください。cpと同様、ディレクトリ転送の-rを忘れると「not a regular file」のようなエラーでスキップされます。
【罠】コロンを忘れると別物になる
もう1つの定番トラブルです。リモート先の:(コロン)を忘れると、scpはそれを「リモート」と認識せず、ただのローカルコピーとして実行します。結果、ホスト名と同じ名前の謎ファイルがローカルにできます。
# NG: コロンが無い scp local.txt user@example.com # → 転送されず、「user@example.com」という名前の # ローカルファイルが作られるだけ! ls # local.txt user@example.com ← 謎のファイル # OK: コロンを付ける(ホームに置くなら : だけでもよい) scp local.txt user@example.com:
実際にコロン無しで実行してみたところ、エラーは出ずに正常終了したように見えて、カレントディレクトリにユーザー名@ホスト名という名前のファイルがコピーされていました。scpは:が無い引数を「ローカルのパス」とみなすため、リモート転送ではなく単なるローカルのcpになってしまうのです。エラーが出ないぶん気づきにくく、「アップロードしたのにサーバーに無い」「変な名前のファイルが増えている」という形で発覚します。リモート指定には必ず:を付ける——ホーム直下でよければuser@host:とコロンで終わればOKです。謎ファイルができてしまったらrm 'user@example.com'のようにクォートして消せます。
実用パターン集
実務でよく使うscpのパターンをまとめます。いずれも実サーバーで動作を確認した形です。
# ポート指定+鍵指定+アップロード(レンタルサーバー定番形) scp -i ~/.ssh/mykey -P 10022 backup.tar.gz user@example.com:/home/user/ # リモートのログをまとめてダウンロード scp -P 10022 "user@example.com:/var/log/app/*.log" ./logs/ # ディレクトリごとバックアップ取得 scp -P 10022 -r user@example.com:/home/user/public_html ./site_backup/ # Windows(PowerShell)でも同じ書き方で使える # scp -i C:\Users\you\.ssh\mykey -P 10022 file.txt user@example.com:/tmp/
リモート側でワイルドカード(*.log)を使うときは、ローカルのシェルに展開されないようクォートで囲むのがポイントです。なお、何度も繰り返す同期や巨大なディレクトリの転送にはrsyncのほうが向いています(変更があったファイルだけを差分転送でき、中断からの再開にも強い)。単発のファイル転送はscp、定期同期はrsyncという使い分けが定番です。WindowsでもPowerShellから同じ構文でそのまま使えます(OpenSSH標準搭載)。
主な書き方一覧
scpの要点をまとめます。
| 書き方 | 働き |
|---|---|
scp ファイル user@host:パス |
アップロード |
scp user@host:パス ローカル |
ダウンロード |
-P 番号(大文字) |
ポート指定(sshは小文字-p) |
-p(小文字) |
タイムスタンプ等の保持 |
-r |
ディレクトリごと転送 |
-i 鍵ファイル |
秘密鍵の指定 |
よくある失敗
小文字-pでポート指定したつもりになる
scpのポートは大文字-Pです。小文字だとport 22に接続しに行ってタイムアウトします。
コロンを忘れてローカルコピーになる
user@host:の:が必須です。忘れるとホスト名のファイルがローカルにできます。
ディレクトリで-rを忘れる
ディレクトリ転送には-rが必要です。
オプションをパスの後ろに書く
-Pや-iは「元・先」の指定より前に書きます。
リモートのワイルドカードをクォートしない
"user@host:/path/*.log"のように囲まないと、ローカル側で展開されて意図がずれます。
よくある質問
scp ローカルのファイル ユーザー@ホスト:リモートのパスで転送できます。cpと同じ「元→先」の順です。ポートが22以外の場合は-P 番号(大文字)、鍵認証なら-i 鍵ファイルを、パス指定より前に付けます。-pで指定していないか確認してください。scpのポート指定は大文字の-Pで、小文字-pは「日時の保持」という別オプションです。実際に小文字で試すと、ポート番号がファイル名として解釈され、既定の22番へ接続しに行ってタイムアウトすることを確認しています。sshは小文字・scpは大文字、という非対称に注意です。:を忘れていないか確認してください。scp file user@hostのようにコロンが無いと、リモート転送ではなくローカルコピーになり、「user@host」という名前のファイルが手元にできるだけです。user@host:のように必ずコロンを付けます。-rを付けてscp -r ディレクトリ user@host:先とします。中のファイル・サブディレクトリごと転送されます。実サーバーでも、ディレクトリ内のファイルが正しく届くことを確認しています。大きなディレクトリの繰り返し同期にはrsyncのほうが効率的です。まとめ
- 転送は
scp 元 先(cpと同じ)。リモートはuser@host:パスで表します。 - ポートは大文字
-P。小文字-pは日時保持で、port 22に行ってしまいます。 - コロン
:を忘れるとローカルコピーになり、ホスト名のファイルができます。 - ディレクトリは
-r、鍵は-i。オプションはパスより前に。 - 繰り返しの同期は
rsyncと使い分けます。
scpは、サーバーとのファイルのやり取りをコマンド一発にしてくれる基本ツールです。実害の大きい罠は「-Pは大文字」「コロンを忘れない」の2つだけ。この2点さえ体に入れれば、デプロイもバックアップ取得も、FTPソフトなしで素早くこなせるようになります。
