今回もファイルのコピー処理の続きです。前回同様ラズベリーパイで動作するのをベースにして書いていますが、特に注意書きがない限りはWindows&Mac PowerShell、UNIX系シェル(bash,zsh)でも動作します。コマンドに慣れていない人はラズベリーパイ上または仮想環境上で実行した方がよいでしょう(ラズベリーパイのインストール・設定等については前回の記事を参照してください)。ファイル操作を行うコマンドに慣れたら実機、本番環境で実行してください。

ファイルのコピー

 それではもっとサイズの大きいファイルをコピーしてみます。ビデオカメラで撮影した映像はサイズが大きいので、それをコピーしてみます。もちろん、他のサイズが大きいファイルがあれば、それでも構いません。また、大量の画像ファイルでも構いません(同じ拡張子のファイルをコピーするサンプルの時に使えますので)。
 ちなみに元となる1つのファイルを大量に連番で複製する場合は以下のようにコマンドを入力します。(bash,zshで動作します。PowerShellでは動作しません)なお、元となるファイルはカレントディレクトリにあるsample.txtです。複製される連番ファイルも同じカレントディレクトリに生成されます。

for i in {1..10};do cp sample.txt ${i}.txt;done

1行でなく複数行で書くと以下のようなコードになります。

for i in {1..10};do
 cp sample.txt ${i}.txt
done

1..10の10を100にすると100個同じファイルが連番で作成されます。ただ、GUIでも対象となるファイルを選択しコピーしペーストを繰り返せば2のn乗で複製が作れますし、今の時代はその方が楽かもしれません。

ということで本題に戻ります。
コピーする映像ファイルですが、外付けのカードリーダーから、ラズベリーパイのデスクトップ上とします。
写真のようにカードリーダーに映像ファイルが入っているSDカードを差し込みます。

SDカードを差し込むとラズベリーパイやWindowsではダイアログが表示される事がありますが、ここでは無視します。

ところでSDカードからコピーするにしても、肝心なSDカード内の映像ファイルの場所がわかりません。WindowsやMacではSDカードはドライブとして認識され自動的にマウントされます。
UNIX系の場合は特定のディレクトリパスの下に配置されます。接続されたドライブなどは、新たなディレクトリパスとしてアクセスできるようになるわけです。ここらへんのマウントポイントは自分で指定する事もできます。マウントポイントはOSや環境によって異なるので、ここではまずラズベリーパイに絞って説明します。

ラズベリーパイの場合、SDカードは以下のディレクトリ内にマウントされます。

/media/pi/

よく分からない場合は、GUIで表示されているSDカードのアイコンの上で右ボタンをクリックします。メニューから「端末で開く」(英語ならopen terminal)を選択します。すると、SDカードがマウントされたディレクトリをカレントディレクトリとして開いてくれます。

ターミナルが起動したらpwdとコマンドを入力すればカレントディレクトリのパスが表示されます。

ここからコピーする映像ファイルがあるディレクトリまでcdコマンドを使って移動します。今回コピーする映像ファイルのパスは長いので、cdコマンドを使って映像ファイルがあるディレクトリまで移動しておきます。
以下のように入力します。

cd /media/pi/CAM_SD/PRIVATE/AVCHD/BDMV/STREAM

一度にパスを入れずに、ひとつずつ確認しながらディレクトリ階層を移動しても構いません。確認する場合はlsコマンドを使えば良いでしょう。lsとだけ入力すればOKです。

cd /media
cd pi
cd CAM_SD
cd PRIVATE
cd AVCHD
cd BDMV
cd STREAM

映像ファイルがあるディレクトリまで移動したらlsコマンドでディレクトリ内にあるファイルを確認します。ここでは2つの映像ファイルがあります。00000.MTSと00001.MTSです。

確認したらcpコマンドで00000.MTSファイルをデスクトップ上にコピーします。

cp 00000.MTS ~/Desktop

ファイルサイズにもよりますが、しばらくするとコピーが終わります。 無事にコピーできればOKです。

同じ拡張子のファイルをコピー

 次に同じ拡張子のファイルをコピーしてみましょう。今回コピーする映像ファイルの拡張子はMTSなので以下のように指定すればデスクトップ上に映像ファイルがすべてコピーされます。*は以前にも使用したワイルドカードです(*記号はすべて対象)。これにより*の後に.MTSの拡張子が続くすべてのファイルがコピー対象になります。ただしディレクトリは対象外です。なお、コピー元のカレントディレクトリは先ほどと同じ映像ファイルがある場所です。

cp *.MTS ~/Desktop

ディレクトリごとコピーする

ただ、さすがにデスクトップ上にファイルをコピーしてしまうと、散らかった感じになってしまいます。世の中、デスクトップがシンプルな人と大量のディレクトリ・ファイルであふれている人がいます。さすがに数千ファイルもデスクトップに散乱しているとわけわからないと思うのですが、どうもディレクトリに入れて整理するのが苦手な人は結構いるようです。Windows/MacのOSの進歩(?)からするとファイルが大量にあるとディレクトリ(フォルダ)を使って整理整頓しても限界があるという感じなのかもしれません。ファイル名&全文検索した方が速いというのが21世紀初頭の結論なのかもしれません。
 先ほどは一つのファイル、特定の拡張子のファイルをコピーしました。これではデスクトップが散らかってしまう原因になるので、今度はディレクトリごとコピーしてみます。ディレクトリごとコピーすればデスクトップにはディレクトリが1つだけなので見た目には整理整頓されているように見えます。

 ディレクトリのコピーもcpコマンドを使います。実行する前に映像ファイルの1つ上のディレクトリに移動しておきます。1つ上のディレクトリに移動するにはcdの後に../を指定します。ちなみに./とした場合はカレントディレクトリ(現在のディレクトリ)を示します。

cd ../

 以下のように入力するとディレクトリごとコピーされるように思えます。しかし、この書き方ではエラーメッセージが表示されディレクトリはコピーされません。

cp STREAM ~/Desktop

ディレクトリごとコピーするには-rのオプションを指定します。-Rのように大文字で指定しても同じです。

cp -r STREAM ~/Desktop

ディレクトリの中身を確認するとディレクトリ内のファイルがすべてコピーされています。なお、rオプションはサブディレクトリもコピーの対象になります。

バックグラウンドでコピーする

 ディレクトリまるごとコピーすると時間がかかる場合があります。ディレクトリだけでなく大量のファイルのコピーなどでも同様です。

先ほどのようにコマンドを入力するとコピーが終了するまで待たなければなりません。こんな時は…新しくターミナルを開いて次の処理、他の処理をしましょう。今は大量のメモリと実質制限なくターミナルが起動でき、コンピュータの速度も速くて快適?ですので、この方法でも問題ないでしょう。

でも、たくさんターミナルを開きたくない、開けない状況もあります。そんな時にはバックグラウンドでコピー処理させる事ができます。バックグラウンドで処理してくれるので、その間に他のコマンドを入力することができます。

先ほどのディレクトリごとバックグラウンドでコピーする場合はコマンドの最後に&をつけます。つまり、コマンドの最後に&をつけるとバックグラウンドで処理されます。PowerShellも同様に最後に&を付ければバックグラウンド処理になります。&はバックグラウンド→バックグラ、アウンド→ア(ウ)ンド→アンド…とまあ、こんな感じで覚えればいいでしょう。

cp STREAM ~/Desktop &

&を指定してコマンドを入力すると、ジョブ番号とプロセスが表示された後、すぐに次のコマンドを入力できる状態になります。ちなみに[ ]内の数値がジョブ番号でその右側の番号がプロセス番号です。

バックグラウンドでコピーした場合、終了しても何も表示されません。終了した場合、リターンキーを押したり何らかの操作をすると、終了したことを示すメッセージが表示されます。処理が終了していない時にリターンキーを押しても何も表示されません。

バックグラウンド処理を行う場合はプロセス処理を制御するps、jobs、bg、fgコマンドを使うことがあります。jobsとbgについては次で説明します。PowerShellでもジョブ関係のコマンドとしてGet-Job、Start-Jos、Stop-Jobがあります。なお、以後の解説はbashおよびzshなどUNIX系が対象です。ちなみにPowerShellでジョブを開始するにはStart-Job { ls }のように指定します。

コピーを止める

 間違ってコピーを開始してしまった場合、停止させるにはcontrol(ctrl)キーを押してからcのキーを押します。Webや本などでctrl+cとして同時に押すように書いてあったりしますが、実際に初学者に教えてみると最初だけうまく伝わらないので先にctrlキーを押してからcキーを押すという具合にしてます。

 コピーを止めるんじゃなくて本当はバックグラウンドで処理するはずだった、という場合もあります。&をつけ忘れてしまった場合です。この場合はコピーを一時停止させてからバックグラウンドで処理するようにします。
 まず、ctrlキーを押してからzキーを押します。するとコピーが一時停止します。「[1]+ 停止 cp -r STREAM ~/Desktop」のように表示されます。この[1]の数値がジョブ番号になります。

ジョブ番号を表示するコマンドはjobsです。jobsと入力するとコピー処理のジョブ番号などが表示されます。[1]の[ ]内の数値がポイントです。

バックグラウンドで処理させるにはbgの後に、このジョブ番号を入力しリターンキーを押します。

bg 1

すると処理がバックグラウンドで継続されます。本当に処理されているかを確認するにはjobsと入力します。すると図のように指定したプロセスが実行中と表示されます。

ファイルコピーいろいろ(bash, zsh)

 bashの機能を利用すると奇数番号のファイルだけコピーすることもできます。今回はコピーするファイルはデスクトップ上のtestディレクトリ内に用意します。コピー先はデスクトップ上のdataディレクトリとします。

カレントディレクトリから1つ上の階層にあるディレクトリ名dataに奇数番号のテキストファイルだけコピーするにはbash,zshでは以下のように書きます。

for i in {1..10..2};do cp ${i}.txt ../data/${i}.txt;done

 偶数番号なら以下のようになります。

for i in {0..10..2};do cp ${i}.txt ../data/${i}.txt;done

 コピーする番号のファイルがない場合でも停止はしません。

 次に特定の名前で始まるファイルをコピーしてみます。以下のようにdataと年月で構成されたファイルがあるとします。

data202101.txt
data202102.txt
data202103.txt
data202104.txt
data202105.txt
data202106.txt
data202107.txt
data202108.txt
data202109.txt
data202110.txt

 ちなみに上記のファイルをbash 4以降,zshで自動的に生成する場合は以下のように入力します。

touch data2021{01..12}.txt

先ほどのコマンドを利用して奇数月だけのデータファイルをコピーする場合は以下のようになります。

for i in {01..12..2};do cp data2021${i}.txt ../data/data2021${i}.txt;done

 偶数月なら以下のようになります。

for i in {02..12..2};do cp data2021${i}.txt ../data/data2021${i}.txt;done

特定の名前で始まるファイルだけコピーすることもできます。以下のようにするとdata2021で始まるファイルで拡張子がtxtのものだけがコピーされます。

cp data2021*.txt ../data

正規表現を使ってコピーする事例は多くありますが、今回はワイルドカードの*だけにしておきます。条件付きでコピーなら、やはりfindとgrepを利用することの方が多いでしょう。これに関しては、またどこかで説明したいと思います。

ログアウトしてもコピーし続けるようにする

 VNCでなくsshなどでリモート接続している場合、サーバー上でコピー処理をさせておきたい場合に使うのがnohupです。sshなどはログアウトしてしまう、接続が切れてしまうとコピー処理などが中断してしまいます。curl等でダウンロードさせておく場合も同様です。
 nohupはログアウトしても、接続が何らかの障害で切れてしまっても処理を継続してくれます。使い方はnohupの後に実行するコマンドを入力するだけです。
 例えばログアウトしても同じ拡張子のファイルをコピーさせておくには以下のように入力します。これでログアウトしてもコピー処理は継続して実行されます。

nohup cp *.MTS ~/Desktop

コピーに関するネタは他にもありますが、とりあえずこのくらいにしておいて次回はファイルの移動、リネームについてです。

著者 仲村次郎
いろいろな事に手を出してみたものの結局身につかず、とりあえず目的の事ができればいいんじゃないかみたいな感じで生きております。