【SSH】scpコマンドでファイル転送する方法|ポートは-P大文字・コロン忘れの罠

【SSH】scpコマンドでファイル転送する方法|ポートは-P大文字・コロン忘れの罠 SSH

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と同じ)になります。

-P と -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
小文字-pだと「port 22でタイムアウト」になる(実証)

実際にポート10022のサーバーへ小文字-pで転送を試したところ、10022がポートではなく「転送するファイルの1つ」として解釈され、既定の22番ポートへ接続しに行ってssh: connect to host ... port 22: Connection timed outで失敗しました。scpの小文字-pcp -pと同じ「タイムスタンプ等の保持」です。「sshは小文字・scpは大文字」という非対称は本当に間違えやすいので、ポート変更済みサーバー(エックスサーバーの10022など)にscpするときは-Pを必ず確認してください。「ポートを指定したはずなのにport 22でタイムアウトする」ときは、まずこの大文字小文字を疑うのが近道です。

ディレクトリ転送(-r)と鍵指定(-i)

ディレクトリごと転送するには-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でディレクトリを中のファイルごとアップロードでき、リモート側で中身が正しく読めました。-isshと同じ書き方で秘密鍵を指定します。オプションは必ず「元パス・先パス」より前に書いてください。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"のように囲まないと、ローカル側で展開されて意図がずれます。

よくある質問

Qscpでサーバーにファイルをアップロードするには?
Ascp ローカルのファイル ユーザー@ホスト:リモートのパスで転送できます。cpと同じ「元→先」の順です。ポートが22以外の場合は-P 番号(大文字)、鍵認証なら-i 鍵ファイルを、パス指定より前に付けます。
Qポートを指定したのにport 22でタイムアウトします。
A小文字の-pで指定していないか確認してください。scpのポート指定は大文字の-Pで、小文字-pは「日時の保持」という別オプションです。実際に小文字で試すと、ポート番号がファイル名として解釈され、既定の22番へ接続しに行ってタイムアウトすることを確認しています。sshは小文字・scpは大文字、という非対称に注意です。
Q転送が成功したように見えるのにサーバーにありません。
Aリモート指定のコロン:を忘れていないか確認してください。scp file user@hostのようにコロンが無いと、リモート転送ではなくローカルコピーになり、「user@host」という名前のファイルが手元にできるだけです。user@host:のように必ずコロンを付けます。
Qディレクトリごと転送するには?
A-rを付けてscp -r ディレクトリ user@host:先とします。中のファイル・サブディレクトリごと転送されます。実サーバーでも、ディレクトリ内のファイルが正しく届くことを確認しています。大きなディレクトリの繰り返し同期にはrsyncのほうが効率的です。
Qscpとrsyncはどちらを使うべきですか?
A単発のファイル転送や少量のやり取りはscpが手軽です。一方、繰り返しの同期・巨大なディレクトリ・回線が不安定な環境では、差分転送と再開に強いrsyncが向いています。「たまの転送はscp、定期同期はrsync」が目安です。

まとめ

  • 転送はscp 元 先(cpと同じ)。リモートはuser@host:パスで表します。
  • ポートは大文字-P。小文字-pは日時保持で、port 22に行ってしまいます。
  • コロン:を忘れるとローカルコピーになり、ホスト名のファイルができます。
  • ディレクトリは-r、鍵は-i。オプションはパスより前に。
  • 繰り返しの同期はrsyncと使い分けます。

scpは、サーバーとのファイルのやり取りをコマンド一発にしてくれる基本ツールです。実害の大きい罠は「-Pは大文字」「コロンを忘れない」の2つだけ。この2点さえ体に入れれば、デプロイもバックアップ取得も、FTPソフトなしで素早くこなせるようになります。