MENU

[Mac/Linux系] 大量のファイルを、漏れなく、破損なく、フォルダごとコピーする。(rsync)

本記事は、以下のような方を対象としています。

  • 大量のファイルをコピーしたい、またはバックアップしたい。
  • 大切なファイルなので、一つも破損して欲しくない。また、漏れなくコピーしたい。
  • PCのOSは、MacまたはLinuxディストリビューション(Ubuntu、CentOS、RHELなど)。(※WindowsでもWSLを導入すれば本手順が実施できます。)
  • PCローカル上でのコピー、またはリモートサーバとの間でのSSHコピーをしたい。

単にファイルをコピーするだけならGUI上でコピペすれば良いですが、大量のファイルをコピペすると以下のような弊害があります。

  • 進捗が見えず、あとどのくらいかかるのかが分からない。
  • 画面やアプリが固まる。
  • コピーのプロセスが落ちて、どこまで完了したのか分からず、また最初から実行する羽目になる。
  • 完了しても、ちゃんと全てのファイルが漏れなく破損なくコピーできたのか不安になる。

そこで、本記事では「rsync」コマンドを用いて、CLI(シェル)上で大量のファイルをコピーする手順をご紹介します。

目次

結論:このコマンドを実行します。

大量のファイルを、漏れなく、破損なく、フォルダごとコピーし、その進捗を監視しつつ、プロセスが落ちても途中から再開できるシェルコマンドは、以下です。

rsync -avh --stats --info=progress2 --no-inc-recursive <コピー元のフォルダパス> <コピー先のフォルダパス>

次章に紹介する手順で、このコマンドを実行していきます。

コマンドで使用している-a-vなどのrsyncのオプションの意味については、「[補足1] 使用しているrsyncのオプション」の章を参照ください。

動作確認環境1では、36,031件の写真・動画ファイル、計220GBを上記コマンドでコピーするのに、13時間16分かかりました。また、「④漏れなく破損なくコピーされたことの確認」の節の実施に、追加で12時間21分がかかっています。

手順

※本手順の動作確認環境は脚注[1]の通りです。

⓪事前準備

  1. シェルを立ち上げます。(Macの場合は「ターミナル」アプリを開きます。)
  2. (コピー時にファイルの所有者やアクセス権限を保持したい場合)以下のコマンドを実行し、管理者権限ユーザ(root)にログインします。元の一般権限ユーザのログインパスワードを求められたら、入力します。
    sudo su -

本手順は管理者権限ユーザでなくても実施できます。ただし、一般権限のユーザのまま実施した場合、コピー後のファイルの所有者はコピーを実施したユーザに変更され、アクセス権限も変更されます。一方で、例えば写真データの撮影日時といったメタデータは、一般権限のユーザによる実行でも保持されるので、所有者やアクセス権限を保持したいケースは多くないかもしれません。以上を認識した上で手順を実施してください。
なお、sudoコマンドを実行できるのは、/etc/sudoersに記載されているユーザのみです。

  1. 以下のコマンドを実行し、本手順内でコマンドとして実行するrsyncのバージョンを確認します。
    rsync --version

rsyncのバージョンが3.1.0より古い場合は、フォルダコピーの全体進捗を表示する--info=progress2のオプションを利用できません。
よって、以下のいずれかの対処をします。
(1) 全体進捗表示が不要な場合:--info=progress2のオプションを利用せず実行する(後述)。
(2) 全体進捗表示が必要な場合:rsyncを最新バージョンにアップデートする。※rsyncのアップデート手順は「[補足2] rsyncのアップデート手順」の章をご参照ください。

バージョンの古いrsyncはコピーにかかる時間も長くなることを確認しているので、(2)をオススメします。

  1. 以下のコマンドを実行し、本手順内で実行するシェルスクリプトを作成します。(10行に渡りますが、一つのコマンドです。)
echo '#!'$SHELL'

echo "$(date '\''+%Y-%m-%d %H:%M:%S'\'') [INFO] $0 process started now."

if rsync -avh --stats --info=progress2 --no-inc-recursive $3 "$1" "$2"; then
  echo "$(date '\''+%Y-%m-%d %H:%M:%S'\'') [INFO] $0 process successfully done!!"
else
  echo "$(date '\''+%Y-%m-%d %H:%M:%S'\'') [ERROR] $0 process failed." 1>&2
fi
' > ./rsync_with_progress.sh

実行したいrsyncのコマンド本体に加え、開始・終了時刻を表示するコマンドを付与しています。また、コマンドが異常終了した場合には標準エラー出力として終了時刻が表示されるようにしています。

  1. 以下のコマンドを実行し、シェルスクリプトを実行できるように権限変更します。
    chmod +x ./rsync_with_progress.sh
  2. 以下のコマンドを実行し、シェルスクリプトを作成したフォルダを確認してメモしておきます。
    pwd
  3. (rsyncのバージョンが3.1.0未満の場合)以下のコマンドを実行し、シェルスクリプトの一部の文字列を置換します。
    sed -i s/'--info=progress2 --no-inc-recursive'/--progress/ ./rsync_with_progress.sh

全体進捗を表示するrsyncのオプション--info=progress2および--no-inc-recursiveが利用できないため、代わりに個々のファイルのコピーの進捗を表示する--progressを指定しています。

  1. (SSH経由でコピーする場合)以下のコマンドを実行し、シェルスクリプトの一部の文字列を置換します。
    sed -i s/-avh/"-avhe 'ssh -o StrictHostKeyChecking=no<その他のsshコマンドオプション>'"/ ./rsync_with_progress.sh
    • 「その他のsshコマンドオプション」が必要ない場合は指定しません。具体的には以下などがあります。
      • -p <リモートサーバのSSHポート番号>: デフォルトの「22」であれば、指定は不要です。
      • -i <秘密鍵のファイルパス>: ログインの認証方式が鍵認証ではなくパスワード認証であれば、指定は不要です。
  2. 作成したシェルスクリプトの内容は、以下のコマンドを実行することで確認できます。
    cat ./rsync_with_progress.sh
  3. 次節以降の手順を実施する前に、コピー元とコピー先のフォルダを具体的に決めておきます(コピーした後にまた別の場所に移動する羽目にならないよう、よく検討して決めます)。

①フォルダのコピーを開始

rsyncに-aオプションを付与した場合でも、タイムスタンプがコピー日時に更新された状態でコピーされる事象を確認しています(WebDAVでマウントしたフォルダにHTTPSを経由してコピーする場合など)。例えば動画データのタイムスタンプが更新されると、時系列情報がバラバラになってしまいます。
そういった不測の事態が起きないことを確認するためにも、まずは小さい規模でテストをしてから本番実施することをオススメします。

  1. シェルを立ち上げます。
  2. (コピー時にファイルの所有者やアクセス権限を保持したい場合※)以下のコマンドを実行し、管理者権限ユーザ(root)にログインします。元の一般権限ユーザのログインパスワードを求められたら、入力します。※「⓪事前準備」の項の2点目を参照。
    sudo su -
  3. 以下のコマンドを実行し、このあと実行するrsyncが想定しているバージョンであるかどうかを改めて確認します。
    rsync --version
  4. 以下のコマンドを実行し、シェルスクリプトのあるフォルダに移動します(「⓪事前準備」の項でメモしたフォルダパスを指定します)。
    cd '<シェルスクリプトのあるフォルダパス>'
  5. 以下のコマンドを実行し、コピー元とコピー先のフォルダパスをそれぞれシェル変数に格納します。
    COPY_SOURCE_PATH='<コピー元のフォルダパス>'
    COPY_DESTINATION_PATH='<コピー先のフォルダパス>'

Macの「Finder」アプリ上でフォルダパスをコピーするには、フォルダを右クリックしてメニューを表示させた状態で「option」キーを押したままにします。するとメニューのうち「”<フォルダ名>”をコピー」が「”<フォルダ名>”のパス名をコピー」に変わるので、「option」キーを押したままその項目をクリックします。

SSH経由でコピーする場合は、リモートサーバのフォルダパスを以下のように指定します。
COPY_SOURCE_PATH='<サーバ上のユーザ名>@<サーバのホスト名またはIPアドレス>:<コピー元のフォルダパス>'
COPY_DESTINATION_PATH(コピー先のフォルダパス)の場合も同様。

コピー元のフォルダパスの末尾にスラッシュ「/」を付けるかどうかで、挙動が変わります。

例)以下のフォルダ構成の場合…
フォルダa
└─フォルダb
   └─ファイルc.txt

'/a/b/' → フォルダbの中のファイル(c.txt)がコピー先フォルダに格納される。
'/a/b' →フォルダbがコピー先フォルダに格納される。

※コピー先のフォルダパスについては、末尾にスラッシュ「/」を付けるかどうかで挙動は変わりません。

  1. 以下のコマンドを実行し、シェル変数に格納されたフォルダパスを表示して、間違いないか確認します。
    echo "$COPY_SOURCE_PATH"
    echo "$COPY_DESTINATION_PATH"
  2. 以下のコマンドを実行し、フォルダのコピーを開始します。
nohup \
./rsync_with_progress.sh "$COPY_SOURCE_PATH" "$COPY_DESTINATION_PATH" \
> ./rsync_$(date +%Y%m%dT%H%M%S).log \
2> ./rsync_error_$(date +%Y%m%dT%H%M%S).log \
&

コマンドをnohup ~ &で実行することで、バックグラウンドプロセスとして実行され、PCがスリープ・シャットダウンするなどでプロセスが停止しない限りは、シェルを閉じても実行され続けます。

  1. (SSH経由でのコピーの場合)リモートサーバへのログインのために、以下の手順でログインパスワードを入力します。公開鍵認証ができ、パスワードの入力が不要な場合は、実施不要です。
    • 以下のコマンドを実行し、対象プロセスのジョブ番号を確認します。
      jobs | grep rsync_with_progress
      • 想定される出力内容は以下の通りです。(プロセスがパスワード入力待機状態のため「Stoppped」になっています。)
        [<ジョブ番号>]+ Stopped nohup ./rsync_with_progress.sh "$COPY_SOURCE_PATH" "$COPY_DESTINATION_PATH" > ./rsync_$(date +%Y%m%dT%H%M%S).log 2> ./rsync_error_$(date +%Y%m%dT%H%M%S).log
    • 以下のコマンドを実行し、対象のプロセスをバックグラウンド(裏)からフォアグラウンド(表)に一時的に移動します。
      fg <対象プロセスのジョブ番号>
    • 以下のようなパスワード入力プロンプトが表示されるので、ログインユーザに対応するパスワードを入力してEnterを押します。
      <サーバ上のユーザ名>@<サーバのホスト名またはIPアドレス>'s password:
      • Enter後に元のローカルPCのプロンプトに戻ってしまった場合は、何らかのエラーが発生していると思われるので、「②-i. 経過確認手順」の項を参照してエラー内容を確認します。
      • Enter後に何も受け付けない状態になれば、正常にプロセスが進行しています。「Ctrl + Z」(Macの場合は「control + Z」)を入力して、一時的にプロセスを停止します。
    • 以下のコマンドを実行し、対象のプロセスを再びバックグラウンドで実行再開します。
      bg <対象プロセスのジョブ番号>

リモートサーバ上でrsyncが特定できない(非対話型で実行する場合のPATHにないなど)、rsyncの実行権限がない、といった原因でエラーになることを確認しています。例えば、シェルスクリプト内のrsyncコマンドにオプション--rsync-pathを指定して、リモートサーバ上のrsyncの場所を教えてあげるなどの方法で対処します。

  1. 以下のコマンドを実行し、ログファイルが2つ新規作成されていることを確認します。
    ls -l rsync_????????T??????.log rsync_error_????????T??????.log

コマンドの実行記録は、ログファイルrsync_<日時を示す文字列>.log(標準出力)とログファイルrsync_error_<日時を示す文字列>.log(標準エラー出力)に書き込まれ続けます。

  1. スリープやシャットダウンをしてしまうと処理が停止してしまうので、自動スリープや自動シャットダウンがPCに設定されている場合は、停止しておきます。(コピーが完了し次第、忘れずに元に戻すことを覚えておきます。)

Macの場合は、以下の設定から自動スリープ(デフォルトでは10分後)をオフにできます。
・macOS 13 Ventura以降
 「システム設定」アプリの「バッテリー」項目
・macOS 12 Monterey以前
 「システム環境設定」アプリの「省エネルギー」項目

②フォルダのコピーの経過確認・中断・再開

②-i. 経過確認手順

ログファイルの中身を確認することで、コピーの経過を確認します。

  1. シェルを立ち上げます。
  2. (コピー時にファイルの所有者やアクセス権限を保持したい場合※)以下のコマンドを実行し、管理者権限ユーザ(root)にログインします。元の一般権限ユーザのログインパスワードを求められたら、入力します。※「⓪事前準備」の項の2点目を参照。
    sudo su -
  3. 以下のコマンドを実行し、シェルスクリプトのあるフォルダに移動します(「⓪事前準備」の節でメモしたフォルダパスを指定します)。
    cd '<シェルスクリプトのあるフォルダパス>'
  4. 以下のコマンドを実行し、ログファイル名を確認します。
    ls -l rsync_????????T??????.log rsync_error_????????T??????.log
  5. 以下のコマンドを実行し、標準エラー出力のログファイルの中身を確認します。
    cat rsync_error_<上で確認した日時を示す文字列>.log
  6. 何も表示されなければ問題ないですが、何らかのエラーがログファイルに書き込まれている場合は、エラー文や以下手順の標準出力のログファイルの内容を読んで対処し、その後「②-iii. (中断した場合)コピーの再開手順」の項を参照して再度コピーを実施してください。
  7. 以下のコマンドを実行し、標準出力のログファイルの中身を閲覧します。
    tail -f rsync_<上で確認した日時を示す文字列>.log

tail -f <ファイル名>とすることで、ファイルの更新行のみを継続的に表示させます。
閲覧を終了する場合は「Ctrl + C」(Macの場合は「control + C」)を入力します。

出力例は以下の通りです(※rsyncのバージョンが3.1.0以上の場合)。進捗状況の読み方と残り時間の概算方法については、「[補足3] 表示されている進捗%から残りのコピー時間を推定できるか」の章を参照ください。

2025-04-04 21:00:05 [INFO] ./rsync_with_progress.sh process started now.
<中略>
2012/12/29/20121229-195544/IMG_0427.JPG  <-- コピー中のファイルパス
         25.79M   0%  928.38kB/s    0:00:27 (xfr#40, to-chk=45070/45125)  <-- 進捗状況
2012/12/29/20121229-195544/IMG_0436.JPG
         27.03M   0%  943.09kB/s    0:00:27 (xfr#41, to-chk=45069/45125)
<中略>
2025-04-04 23:10:07 [INFO] ./rsync_with_progress.sh process successfully done!!

②-ii. コピーの中断手順

何らかの理由でコピーを中断する必要が出た場合は、PCをそのままシャットダウンするか、以下の手順で実行中のプロセスを強制終了します。

  1. シェルを立ち上げます。
  2. 以下のコマンドを実行し、シェルスクリプトが実行されているプロセスのプロセスID(PID)を確認します。シェルスクリプトが複数のプロセスで並行して動いている場合は、複数のプロセスIDを確認します。
    ※ヘッダー行以外何も表示されない場合は、既にプロセスは停止しています。
    ps aux | grep -v grep | grep -e PID -e rsync_with_progress
  3. 以下のコマンドを実行し、シェルスクリプトのプロセスを強制終了します。パスワードの入力を求められるので、実行しているユーザのPCログインパスワードを入力します。シェルスクリプトが複数のプロセスで並行して動いている場合は、その全てについて強制終了します。
    sudo kill -9 <対象のプロセスID>
  4. 以下のコマンドを実行し、ヘッダー行以外何も表示されないことを確認します。
    ps aux | grep -v grep | grep -e PID -e rsync_with_progress

関係のないプロセスのプロセスIDを指定してしまうと、予期せずPCの重要なプロセスを強制終了してしまう恐れがあります。よく確認して、正しいプロセスIDを指定するように気をつけましょう。

②-iii. (中断した場合)コピーの再開手順

PCが予期せずシャットダウンするなどの理由で、コピーが中断した場合は、「①フォルダのコピーを開始」の節の手順を再度実行し直すことで、コピーを再開できます。その際、ログファイルは別の新規ファイルとして作成されます。

rsyncコマンドは差分コピーをするため、同じコピー先フォルダを指定すれば、既にコピーされたファイルは改めてコピーせず、まだコピーされていないファイルのみをコピーします。
ただし、既にコピーされたファイルのスキップがゼロ時間になる訳ではないので、同程度の実行時間を要します。シェル変数COPY_SOURCE_PATHおよびCOPY_DESTINATION_PATHを、まだコピーされていないファイルを全て含むサブフォルダに指定し直すことで、実行時間を短縮することができます。

③フォルダのコピーの完了確認

コピーのシェルスクリプトが正常に完了したかどうかを確認します。

  1. シェルを立ち上げます。
  2. (コピー時にファイルの所有者やアクセス権限を保持したい場合※)以下のコマンドを実行し、管理者権限ユーザ(root)にログインします。元の一般権限ユーザのログインパスワードを求められたら、入力します。※「⓪事前準備」の項の2点目を参照。
    sudo su -
  3. 以下のコマンドを実行し、シェルスクリプトが実行されているプロセスを確認します。
    ps aux | grep -v grep | grep -e PID -e rsync_with_progress
    • ヘッダー行以外に表示される場合は、プロセスが終了していないため、引き続きコピ-完了まで待機します。
    • ヘッダー行以外に何も表示されない場合は、既にプロセスは停止しています。コピーが全て完了したか、一部失敗して完了したか、プロセスが中断された可能性があるので、いずれなのかを以下の手順で確認します。
  4. 以下のコマンドを実行し、シェルスクリプトのあるフォルダに移動します(「⓪事前準備」の節でメモしたフォルダパスを指定します)。
    cd '<シェルスクリプトのあるフォルダパス>'
  5. 以下のコマンドを実行し、ログファイル名を確認します。
    ls -l rsync_????????T??????.log rsync_error_????????T??????.log
  6. 以下のコマンドを実行し、標準出力のログファイルの中身から文字列「process successfully done」を検索します。
    grep -B 20 'process successfully done' rsync_<上で確認した日時を示す文字列>.log
    • ファイルの末尾が表示されたら、コピーが全て無事に完了しています。
    • 何も表示されない場合は、一部のコピーが失敗したか、コピー完了前にプロセスが中断されています。
  7. 以下のコマンドを実行し、標準エラー出力のログファイルの内容を確認します。
    cat rsync_error_<上で確認した日時を示す文字列>.log
    • 末尾に「./rsync_with_progress.sh process failed.」と表示されていれば、一部のコピーが失敗しています。エラー文や標準出力のログファイルの内容を読んで対処し、その後「②-iii. (中断した場合)コピーの再開手順」の項を参照して再度コピーを実施してください。
    • 末尾に「./rsync_with_progress.sh process failed.」と表示されていなければ、コピー完了前にプロセスが中断されています。「②-iii. (中断した場合)コピーの再開手順」の項を参照してコピーを再開してください。

コピー元・コピー先のフォルダによっては、実行しているユーザの権限ではアクセスできない場所にあり、ファイルコピーがエラーとなる場合があります。その場合のコピー再実施時はsudo su -を実行します(「①フォルダのコピーを開始」の節の手順の冒頭)。実行ユーザが変わることで実行するrsyncのバージョンが変わる場合もあるので、ご注意ください。

標準出力のログファイル末尾は、以下のように表示されます。(例えば、4行目と6行目から、コピーされたファイル数と総ファイルサイズがわかります。)

Number of files: 45,125 (reg: 36,031, dir: 9,094)  <-- コピー元のファイル&フォルダの総数
Number of created files: 45,124 (reg: 36,031, dir: 9,093)  <-- コピー先で生成されたファイル&フォルダの総数
Number of deleted files: 0  <-- コピー先で削除されたファイル&フォルダの総数
Number of regular files transferred: 36,031  <--- コピーされたファイル数
Total file size: 219.90G bytes  <-- コピー元の総ファイルサイズ
Total transferred file size: 219.90G bytes  <-- コピーされた総ファイルサイズ
Literal data: 219.90G bytes  <-- 実際に送信されたデータサイズ
Matched data: 0 bytes  <-- コピー先と一致してスキップされたデータサイズ
File list size: 704.47K  <-- コピーファイル一覧情報のデータサイズ(bytes)
File list generation time: 5.208 seconds  <-- コピーファイル一覧情報の作成にかかった時間
File list transfer time: 0.000 seconds  <-- コピーファイル一覧情報の転送にかかった時間
Total bytes sent: 219.96G  <- コピー元からコピー先に送信したデータの総サイズ(bytes)
Total bytes received: 711.98K  <- コピー先からコピー元に送信したデータの総サイズ(bytes)

sent 219.96G bytes  received 711.98K bytes  4.61M bytes/sec  <-- データの平均転送速度
total size is 219.90G  speedup is 1.00  <-- 転送効率(コピー対象の総ファイルサイズ/実際にコピーされた総ファイルサイズ)
2025-04-05 10:28:52 [INFO] ./rsync_with_progress.sh process successfully done!!

④漏れなく破損なくコピーされたことの確認

前節まででコピーが完了したと思われるので、-cオプションを用いて、破損なく完全コピーされたかどうかを確認します。

  1. ①フォルダのコピーを開始」の節の手順を再度実施します。
    ただし、メインで実行するスクリプトに、以下のように-cオプションを末尾に追加することで、コピー元とコピー先とで、「チェックサム」が異なるファイルが存在しないか確認します。
nohup \
./rsync_with_progress.sh "$COPY_SOURCE_PATH" "$COPY_DESTINATION_PATH" '-c' \
> ./rsync_$(date +%Y%m%dT%H%M%S).log \
2> ./rsync_error_$(date +%Y%m%dT%H%M%S).log \
&

「チェックサム」とは、データをある単位で区切って全て足し合わせた数を意味し、データの同一性を確認するために使用される計算方法、またはその結果のことです。rsyncにオプション-cを指定すると、コピー元とコピー先とのデータの同一性チェックを、更新日とサイズではなく、チェックサムで実施してくれます。

  1. ③フォルダのコピーの完了確認」の節を参考に、コピーされたファイル数を確認します。
    • コピーされたファイル数が0件の場合、全てのファイルがチェックサムレベルで同一で、1度目のコピー完了の時点で破損なくコピーされていたことを確認できます。
    • コピーされたファイル数が1件以上ある場合、1度目のコピーの際に破損してコピーされたファイルが存在していたことがわかります。その場合、今回の実行により改めてコピーされたはずですが、そのコピーが破損ないかどうか念のため再確認するのであれば、本節の手順を再実施します。

再実施する際は、シェル変数COPY_SOURCE_PATHおよびCOPY_DESTINATION_PATHを、再確認対象ファイルを全て含むサブフォルダに指定し直すことで、実行時間を短縮することができます。

  1. 自動スリープや自動シャットダウンの設定を停止していた場合は、すべて完了したあとに設定を元に戻しておきます。
筆者

手順は以上です。
ここまで読んでいただき、ありがとうございました!

[補足1] 使用しているrsyncのオプション

※下記の説明の多くについて、こちらのWebサイト2より引用しています。

オプション説明
-aアーカイブモード(「-rlptgoD --no-H --no-A --no-X」に相当。それぞれのオプションは以下。)
-rフォルダを再帰的に処理する
-lシンボリックリンクをシンボリックリンクのままコピーする
-pパーミッションを保持する
-tタイムスタンプを保持する
-g所有グループをそのまま保持する
-o所有者をそのまま保持する(自分以外の所有者を保持するにはroot権限が必要)
-Dデバイスファイルや特殊ファイルを保持する
--no-Hハードリンクを保持しない
--no-AACL(アクセス制御リスト)を保持しない
--no-X拡張属性を保持しない
-v動作内容を表示する
-h数字を読みやすい単位で表示する
--statsファイル数や転送サイズを表示する
--info=progress2[>=3.1.0] (処理全体に対して)コピーの進行状況を表示する3
--no-inc-recursive[>=3.1.0] recursive algorithmをオフにすることで、コピー開始前にフォルダ構造を全て解析するようにする[3]
--progress(1ファイルごとに)コピーの進行状況を表示する
-eリモートシェルを指定する(デフォルト値:rsh [<2.6.0] / ssh [>=2.6.0])4。リモートシェルのポート番号を指定する場合や、公開鍵認証を用いる場合など、オプションを指定する必要がある場合は、リモートシェルのコマンドを含めた文字列として渡す(例:-e 'ssh -p 2345'5
-c更新日とサイズではなく、チェックサムで変更の有無をチェックする
--rsync-pathリモートサーバ間でコピーする場合、リモートサーバ上のrsyncコマンドのパスを指定する
--dry-run試験モード。実際には動作せず、動作内容だけ表示する
-uコピー先のファイルの方が新しい場合はコピーせずにスキップする
-m空のフォルダはコピー対象にしない

[補足2] rsyncのアップデート手順

Macの場合

  1. 「ターミナル」アプリを立ち上げます。
  2. (コピー時にファイルの所有者やアクセス権限を保持したい場合※)以下のコマンドを実行し、管理者権限ユーザ(root)にログインします。元の一般権限ユーザのログインパスワードを求められたら、入力します。※「⓪事前準備」の項の2点目を参照。
    sudo su -
  3. 以下のコマンドを実行し、現時点の実行対象のrsyncのバージョンを確認しておきます。
    rsync --version
  4. 以下のコマンドを実行し、現時点の実行対象のrsyncがどこにあるかを確認しておきます。
    which rsync
  5. 以下のコマンドを実行し、Macのパッケージ管理ツール「Homebrew」がインストールされていることを確認します。バージョンが表示されずにエラーとなる場合は、インストールされていません。
    brew --version
  6. (Homebrewがインストールされていない場合)以下のコマンドを実行し、Homebrewをインストールします。(コマンドは脚注6の公式HPから引用。)
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  7. (Homebrewがインストールされている場合)以下のコマンドを実行し、Homebrewのバージョンを最新化します。
    brew update
  8. 以下のコマンドを実行し、Homebrewでrsyncがインストールされているかどうかを確認します。何も表示されなければ、Homebrewではインストールされていません。
    brew list | grep rsync
  9. (Homebrewでrsyncがインストールされていない場合)以下のコマンドを実行し、Homebrewでrsyncをインストールします。
    brew install rsync
  10. (Homebrewでrsyncがインストールされている場合)以下のコマンドを実行し、Homebrewのrsyncをアップデートします。
    brew upgrade rsync
  11. 以下のコマンドを実行し、現時点の実行対象のrsyncがどこにあるかを確認します。
    which rsync
    • /usr/local/bin/rsyncと表示: Homebrewでインストールしたrsyncが実行対象になっているため問題ありません。以下のコマンドを実行して、rsyncのバージョンが最新化されていることを確認し、rsyncのアップデートは完了です(以降の手順を実施する必要はありません)。
      rsync --version
    • /<それ以外の場所>/rsyncと表示(冒頭で確認した場所から変わっていない): 元々インストールされていたrsyncが引き続き実行対象になっています。以降の手順を実施して、Homebrewでインストールしたrsyncを実行対象にします。

Homebrewはデフォルトでは/usr/local/bin/brewにインストールされ、各パッケージは/usr/local/bin配下にインストールされますが、Homebrewのインストール先をカスタマイズしている場合は条件が異なるのでご注意ください。

  1. 以下の4つのコマンドを実行し、Homebrewでインストールしたrsyncが優先して実行されるように、実行ユーザの環境変数PATHを永続的に変更します。
    echo 'export PATH=/usr/local/bin:$PATH' >> ~/.profile
    source ~/.profile
    if [ -f ~/.bash_profile ];then sed -i '1isource ~/.profile' ~/.bash_profile;fi
    if [ -f ~/.zprofile ];then sed -i '1isource ~/.profile' ~/.zprofile;fi
  2. 以下のコマンドを実行し、/usr/local/bin/rsyncと表示されることで、Homebrewでインストールしたrsyncが実行対象になったことを確認します。
    which rsync
  3. 以下のコマンドを実行し、Homebrewでインストールしたrsyncのバージョンが最新化されていることを確認します。
    rsync --version

Ubuntu/Debian系OSの場合

  1. sudoコマンドで管理者権限を持つことができるユーザ(※)でシェルにログインします(※/etc/sudoersに記載されているユーザ)。
  2. 以下のコマンドを実行し、パッケージ管理ツール「APT」により更新可能な最新パッケージを全取得してきます。パスワードが求められたら、実行ユーザのログインパスワードを入力します。
    sudo apt update
  3. 以下のコマンドを実行し、APTでrsyncを最新バージョンにアップデートします。インストールされていない場合は、インストールします。
    sudo apt install rsync
  4. APTによりrsyncが最新化されたことを確認します。
    rsync --version

CentOS/RHEL系OS・Fedoraの場合

  1. sudoコマンドで管理者権限を持つことができるユーザ(※)でシェルにログインします(※/etc/sudoersに記載されているユーザ)。
  2. 以下のコマンドを実行し、パッケージ管理ツール「Dandified Yum」により更新可能な最新パッケージを全取得してきます。パスワードが求められたら、実行ユーザのログインパスワードを入力します。
    sudo dnf check-update
    • 古いOSでは「dnfというコマンドがない」というエラーになるので、その場合は以下のように前身の「Yum」を使用します。
      sudo yum check-update
  3. 以下のコマンドを実行し、Dandified Yumでrsyncを最新バージョンにアップデートします。インストールされていない場合は、インストールします。
    sudo dnf install rsync
    • Dandified Yumが存在しない場合は以下を実行します。
      sudo yum install rsync
  4. Dandified Yumによりrsyncが最新化されたことを確認します。
    rsync --version

[補足3] 表示されている進捗%から残りのコピー時間を推定できるか

rsync(バージョン3.1.0以上)にオプション-v-h--info=progress2--no-inc-recursiveを指定したときの進捗状況のログ出力は以下のようになります7

34.46G【イ】  15%【ロ】    2.44MB/s【ハ】    3:44:31【ニ】 (xfr#16104【ホ】, to-chk=25177【ヘ】/45125【ト】)

(イ)コピー済みのデータサイズ(バイト)
(ロ)コピー予定のデータサイズのうち転送済みのデータサイズの進捗%
(ハ)現在のデータ転送速度(バイト毎秒)
(ニ)現在までのコピー所用時間(hh:mm:ss)
(ホ)現在処理中のファイルが何個目か
(ヘ)処理対象のファイルおよびフォルダが、あと何個残っているか
(ト)処理対象のファイルおよびフォルダの全個数

よって、データ転送速度(ハ)が一定でさえあれば、現在までの所用時間(ニ)と進捗%(ロ)の情報を用いて、以下のように残りの所用時間を計算できるはずです。
<残りの所用時間> = <現在までの所用時間(ニ)> × ( 100% ÷ <進捗%(ロ)> - 1 ) ・・・式(*)

上記の15%時点の例の場合は、3:44:31 × ( 100% ÷ 15% - 1) = 21:12:10 となり、あと21時間強かかると推定されます。しかし、実際にコピー全体にかかった時間は13時間16分でしたので、ここまでの3:44:31を差し引くと、実際よりも2倍以上の残り時間が推定されてしまっています。

原因としては、データ転送速度(ハ)の変動が考えられます。以下の図をご覧ください。

図 経過時間に対するコピーの進捗%推移

コピー全体に実際にかかった時間から逆算した場合の、表示されて欲しい理想的な進捗%推移(図中の橙色点線)と比較すると、実際に表示されていた進捗%推移(図中の藍色実線)は常に下回っています。これにより、3:44:31経過時点で残り時間を推定したとしても、実際よりも遙かに長い時間となってしまうことがわかります。

ここで、データ転送速度(灰色実線)に注目すると、3:44:31時点では2,499kB/sですが、最終的には4,495kB/sまで上昇しています。よって、先述の式(*)の前提となる「データ転送速度が一定」という条件が正しくなかったことが原因で、残り時間の推定が上手くいっていないことがわかります。

なぜ今回のコピーで、データ転送速度が徐々に上昇しているのかは正確にはわかりませんが、恐らくコピー元のPCとコピー先のサーバのCPUなどの空き状況に起因すると思っています。特に最初の3~4時間はPC上で別の作業をしていましたので、その作業にリソースを取られてコピーが捗らなかったのだと思います。

したがって、ログ出力の内容から式(*)を用いることで、残りのコピー時間を推定できますが、飽くまで「その時点までの平均データ転送速度が維持された場合」という仮定の下であることに注意が必要です。その時点以降にデータ転送速度が上昇するか下降するかは、なかなか予測できないかと思いますが、その可能性を考慮しておきましょう。

脚注

  1. 本手順の動作確認環境
    [全体手順確認]
    ・Mac OS 10.13.6
    ・Bash 3.2.57(1)-release
    ・Homebrew 4.4.24
    ・rsync 3.4.1
    [SSH・Ubuntu手順確認]
    ・Ubuntu 22.04.3 LTS (on Windows11 WSL)
    ・Bash 5.1.16(1)-release
    ・APT 2.4.11 (amd64)
    ・rsync 3.2.7 ↩︎
  2. “rsyncコマンド(その1)――ファイルやディレクトリを同期する:Linux基本コマンドTips(82) – @IT”, https://atmarkit.itmedia.co.jp/ait/articles/1702/02/news031.html. ↩︎
  3. “[Linux] rsyncで進捗を確認する”, https://to-31.blogspot.com/2018/04/linux-rsync.html. ↩︎
  4. “rsync 2.6.0 以降は -e ssh がデフォルトです | キュア子の開発ブログ”, https://curecode.jp/tech/rsync-default-remote-shell-is-ssh/. ↩︎
  5. “rsyncで公開鍵を指定してデータ転送する方法 – yoshiyoshi-1413’s blog”, https://yoshiyoshi-1413.hatenablog.com/entry/2018/03/12/162848. ↩︎
  6. “macOS(またはLinux)用パッケージマネージャー — Homebrew”, https://brew.sh/ja/. ↩︎
  7. “Understanding the output of –info=progress2 from rsync – Unix & Linux Stack Exchange”, https://unix.stackexchange.com/questions/215271/understanding-the-output-of-info-progress2-from-rsync. ↩︎

この記事が気に入ったら
フォローしてね!

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

筆者

ユーマン
在籍: 大手SIer企業
職務: Python歴7年の開発職
大学: ロボ設計/PV制作 @NHKロボコン優勝サークル
大学院: 学会発表にて2度優秀賞 @AI研究
目標: ふと思いついたモノを何でもつくれちゃう人
好き: Python / Excel / 定時退社 / カフェ作業 / 自己分析 / 友達と遊ぶこと / ホラー映画 / '00年代アニメ / 散歩or登山 / スキー / Mr.Children / 笑顔がステキな方
目次