続・基本的なUNIXコマンド

目次

Unknown programmer's programming note.

<2022-01-02 日>

1 概要

Hello Worldのプログラムを動かすために必要となる基本的なUNIXコマンドを解説するのはこれが最後の回となります。 前回前々回では、関連するUNIXの基礎も含めて解説したかったので、かなり長々と書いてきました。 今回紹介するコマンドでは寄り道しないで、コマンド本来の目的に絞って解説していこうと思います。 だいぶあっさりとした内容にするつもりです。

2 仮想マシンのスナップショットを作成する

寄り道しないと言ったばかりですが、さっそく本来の目的とは関係のない作業をしなければなりません。 これから紹介するコマンドはファイルやディレクトリを作成したり削除したり変更を加えるものになります。 そういった作業は誤ってシステムを破壊してしまう可能性があるので対策をしておきます。

2.1 なぜスナップショットを利用するのか

現在ログインして作業を行なうユーザーはrootという名前のユーザーです。 このユーザーはFreeBSDにとって特別なユーザーで、スーバーユーザーとか管理者などとも呼ばれます。

rootはログインしているシステムに対してあらゆる変更を許可されています。 例えば /bin というディレクトリをコマンド一発で削除してしまったり /boot にあるシステムの起動に必要なファイルをでたらめな内容に破壊してしまったりです。

UNIXを使い始めたばかりの人が真先に叩き込まれる教えが「自分しか使わない環境でもrootでログインして作業を行うな」といった類のものです。 どうするかというと、rootのような強力な権限を持たない一般ユーザーを作成して、普段はそのユーザーでログインします。 何かシステム全体に変更を加える操作を行うために権限が必要なときにのみ、rootの権限に変更して操作を行います。 具体的にはsuやsudoというコマンドを利用します。

今ここで一般ユーザーを作成して、sudoを使えるようにすることも可能ですが、Hello Worldからどんどん遠のいてしまい、「初めてのプログラミング」というタイトルから逸れてしまいたくないのでそうはしません。 代わりに、VirtualBoxのスナップショットという機能を使って、いつでも手軽に保存していた時点の状態に戻せるようにしておきます。

スナップショットの代わりにクローンを利用することもできますが、クローンはディスクのイメージをまるまる複製するため、容量を食います。 スナップショットはディスクのイメージの複製は行いません。 気軽に利用できるし、復元も管理するのもVirtualBoxマネージャーから簡単に、気軽に行えます。 VirtualBoxを使うならぜひとも使い方を覚えておいたほうがいいと思います。

2.2 スナップショットの作成

スナップショットを作成を開始するには、2つルートがあります。

  1. 実行中の仮想マシンのウィンドウのメニューから作成
  2. VirtualBoxマネージャーのスナップショット専用のビューから作成

1)は仮想マシンのウィンドウで作業しているとき、すぐに作成できるので手軽です。ショートカットキーまで用意されています。

2)はスナップショットの他の操作もまとまっているので、管理しやすいです。復元するにはこちらから行います。

両方のスクリーンショットを載せておきます。

VirtualBox create snapshot on VM window

図1: 仮想マシンのウィンドウのメニューから作成

VirtualBox create snapshot on manager

図2: VirtualBoxマネージャーから作成

どちらから作成を選択しても次のようなダイアログが表示されます。

VirtualBox create snapshot dialog

図3: スナップショット作成のダイアログ

名前は後からでも自由に変更できます。 しかし、すぐに何ためのスナップショットだったのか分からなくなってしまうので、できるだけ分かりやすい名前を付けるほうが良いです。 スナップショットを作成すると、VirtualBoxマネージャーに登録され管理できるようになります。

VirtualBox create snapshot after created

図4: スナップショット作成後のVirtualBoxマネージャー

「プロパティ」ボタンをクリックすると、名前や説明の変更をしたり、スナップショット作成時の仮想マシンの状態の確認ができます。

スナップショットは、最初に作成したものを起点として、木構造で管理されます。 例えば、今、もう一つスナップショットを作成すると次のようになります。

▾ほぼ初期状態
    ▾スナップショット1
        🗹最新の状態

さらに続けてもう一つ作ると次のようになります。

▾ほぼ初期状態
    ▾スナップショット1
        ▾スナップショット2
            🗹最新の状態

ここで、最初に作った「ほぼ初期状態」という名前のスナップショットに復元します。

▾ほぼ初期状態
    ▾スナップショット1
        ▾スナップショット2
            🗹最新の状態

「最新の状態」が移動しました。

そして、この状態でもう一つスナップショットを作成します。

▾ほぼ初期状態
    ▾スナップショット1
        ▾スナップショット2
    ▾スナップショット3
        🗹最新の状態

「ほぼ初期状態」の直下に新しいスナップショットが作成されました。

「最新の状態」というのが現在使用中のスナップショットを示しています。 そして、新しくスナップショットを作成するとその配下に作成されるといった具合です。 文章や図では伝わりにくいとは思いますが、実際に使ってみるととても扱いやすいです。 現在の状態も保存した上で、気軽に過去のある時点の状態に戻して、そこから分岐させたりできます。

確実性という点ではクローンの方が勝ります。 しかし、クローンはディスクのイメージをまるまる複製するので気軽にはできません。 うまく使い分けていくと良いです。

2.3 スナップショットからの復元

復元は簡単です。 まず仮想マシンを閉じておく必要があります。 そしてVirtualBoxマネージャーのスナップショットを管理するビューで、復元したいスナップショットを選択します。 あとは「復元」ボタンを押すだけです。

復元すると現在の状態が失なわれてしまうので、現在の状態をスナップショットとして残しておくかどうかを尋ねられます。

  • 失われてはいけないなら、チェックを入れておきます。 チェックが入っていると、スナップショットの作成のところでもでてきた、作成のダイアログが表示されるので、作成します。 作成後に復元されます。
  • 失われてもいいなら「現在のマシンの状態のスナップショットを作成」のチェックを外しておきます。 チェックが外れていると、そのまま現在の状態を破棄して復元されます。

VirtualBox restore snapshot dialog

図5: スナップショットの復元の確認ダイアログ

VirtualBoxのスナップショットについては以上です。 これでいつでも元に戻せるようになったので、安心して次に進むことができます。

3 ディレクトリを作成する: mkdir

これまでの知識では、FreeBSDのディレクトリ構造を徘徊したり覗いたりすることしかできませんでした。 今、初めてFreeBSDに対して何か能動的に意味のある変化を与える瞬間となりました。

まずディレクトリを作成することから始めます。 現在rootでログイン中なのでどこにでもディレクトリを作成して、思いのままのディレクトリ構造を作ることも可能です。 しかし、無駄に破壊的なことをするのは止めておいて、安全にrootのホームディレクトリである /root の中でのみ作業するとにしましょう。 それでも誤って何かを破壊してしまう可能性を考慮して、もしスナップショットを作成していないなら、前のセクションに戻って作成しておくことをお勧めします。

ディレクトリの作成に使うコマンドはmkdirです。 MaKe DIRectory の略です。 使い方はいたって直感的です。

root@freebsd:~ # pwd⏎         ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # mkdir mybag⏎ ▹ディレクトリ mybag を作成
root@freebsd:~ # ls mybag⏎    ▹ディレクトリが作成されたことを確認(何も表示されないはず)
root@freebsd:~ # ▋

作成されたようです。 その中に移動してみます。

root@freebsd:~ # pwd⏎         ▹現在のディレクトリがrootのホームディレクトリであることを確認
root@freebsd:~ # cd mybag⏎    ▹mybag の中に移動
root@freebsd:~/mybag # ls⏎    ▹mybag の中身を表示(何もないはず)
root@freebsd:~/mybag # pwd⏎   ▹現在のディレクトリが mybag であることを確認
/root/mybag
root@freebsd:~/mybag # ▋

無事に移動できました。

※ここでlsは指定されたディレクトリの中に何もない場合、何も表示しないことには注意してください。

mkdirに複数の引数を与えることもできます。 その場合、与えられた全ての名前のディレクトリを作成します。

root@freebsd:~/mybag # pwd⏎                  ▹現在のディレクトリが mybag であることを確認
/root/mybag
root@freebsd:~/mybag # mkdir egg milk apple⏎ ▹ディレクトリを3つ作成
root@freebsd:~/mybag # ls⏎                   ▹mybag の中身を表示
apple   egg     milk 
root@freebsd:~/mybag # ▋

カレントディレクトリの中だけでなく、パスを指定することでどこにでも作成できます。 パスは絶対パスでも相対パスでもOKです。

root@freebsd:~/mybag # pwd⏎                          ▹現在のディレクトリが mybag であることを確認
/root/mybag
root@freebsd:~/mybag # mkdir egg/chicken⏎            ▹相対パスでディレクトリを作成
root@freebsd:~/mybag # ls egg⏎                       ▹作成したディレクトリの中身を表示
chicken 
root@freebsd:~/mybag # mkdir /root/mybag/egg/cheese⏎ ▹絶対パスでディレクトリを作成
root@freebsd:~/mybag # ls egg⏎                       ▹ディレクトリ cheese が作成されたことを確認
cheese  chicken
root@freebsd:~/mybag # ▋

しかし、パスの途中に存在しないものが含まれていてはいけません。

root@freebsd:~/mybag # pwd⏎                        ▹現在のディレクトリが mybag であることを確認
/root/mybag
root@freebsd:~/mybag # mkdir egg/icecream/pudding⏎ ▹途中に存在しないディレクトリを含むパスで作成を試行
mkdir: egg/icecream: No such file or directory
root@freebsd:~/mybag # ▋

上の例では、icecreamが存在していないため、その中に新しく作成することができません。 このようなケースでは -p オプションが便利です。 mkdir -p a/b/c/d のようにすると、パスを構成するそれぞれディレクトリが存在しない場合でも、全て作成します。

root@freebsd:~/mybag # pwd⏎                           ▹現在のディレクトリが mybag であることを確認
/root/mybag
root@freebsd:~/mybag # mkdir -p egg/icecream/pudding⏎ ▹パスの途中のディレクトリもまとめて作成
root@freebsd:~/mybag # ls egg egg/icecream⏎           ▹ディレクトリが作成されたことを確認
egg:
cheese          chicken         icecream

egg/icecream:
pudding 
root@freebsd:~/mybag # ▋

mkdirについては以上です。

4 ディレクトリを削除する: rmdir

mkdirと対になるrmdirというコマンドが存在します。 ReMove DIRectory の略です。

rmdirは引数で指定されたディレクトリを削除します。 引数は複数取ることができます。 rmdir dir1 dir2 のようにします。 引数のディレクトリはmkdirのときと同じように、パスを指定することでカレントディレクトリ以外の場所にあるディレクトリを削除することができます。 rmdir xxx/yyy/dir3 といった具合です。

このコマンドはmkdirに比べると、それほど使用頻度は高くないです。 なぜなら、rmdirは削除する対象のディレクトリが空でないといけないからです。 日常的な作業では、空のディレクトリを削除する必要がある状況よりも、ディレクトリの中に何か含まれていて、それも一緒に削除したい状況の方が多いです。 中身もまとめて削除するには後で紹介するrmを使うことができます。 しかし、rmは何でも削除できてしまうので危険が付き纏います。 一方rmdirは空でなけらば削除できないので、割と安全です。

前のmkdirのところで作ったディレクトリを使って試してみましょう。

root@freebsd:~ # pwd⏎               ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~/# cd mybag⏎          ▹前に作ったディレクトリ mybag に移動
root@freebsd:~/mybag # ls⏎          ▹ディレクトリの中身を確認
apple   egg     milk
root@freebsd:~/mybag # rmdir apple⏎ ▹apple を削除
root@freebsd:~/mybag # ls⏎          ▹apple が削除されたことを確認
egg     milk
root@freebsd:~/mybag # ▋

空ではないディレクトリの削除を試してみましょう。

root@freebsd:~/mybag # pwd⏎             ▹現在のディレクトリが mybag であることを確認
/root/mybag
root@freebsd:~/mybag # ls egg⏎          ▹egg が空でないことを確認
cheese          chicken         icecream
root@freebsd:~/mybag # rmdir egg⏎       ▹空でないディレクトリ egg の削除を試行
rmdir: egg: Directory not empty
root@freebsd:~/mybag # ▋

「ディレクトリが空ではない」というメッセージが返ってきました。

mkdirに -p オプションがあったのと同様、rmdirにも -p オプションがあります。 動作は丁度 mkdir -p xxx/yyy/dir1 と逆になります。 例えば rmdir -p xxx/yyy/dir1 とした場合、xxxとyyyとdir1は存在していなければなりません。 なおかつ空でなければいけません。 しかし、もし、dir1が空で、yyyがdir1以外のものを含んでいたら、dir1だけ削除されて、残りは削除されません。

rmdir -p はあまり使わないのですが、mkdirとの対称性を強調するために一応触れておきました。

5 ファイルの内容を表示する: cat

catはファイルの内容を画面に表示します。

…というのはあまり正確ではありません。 名前の由来は conCATenate で「連結する」というような意味です。 なぜこのような名前のコマンドがファイルの内容を表示するのか分かりづらいところがあるかと思います。 差し当たり cat a.txt b.txt c.txt とすると、引数で指定された全てのファイルの内容を画面に出力することから「連結する」ことのように見えるからとしておきます。 catが本来意図されていた使い方を知るには、もう少しUNIXについて知らないといけないです。

今覚える必要のあるcatの使い方は 引数で指定されたファイルの内容を画面に表示する ことだけです。 まだファイルの中身を一つも見ることができていないので、この機能だけでもとてもありがたいものです。

catの引数はファイルです。 パスで指定してカレントディレクトリ以外のファイルを与えることもできます。 例えば cat /etc/rc.conf です。

試しにrootのホームディレクトリにあったファイルのいくつかを表示してみましょう。

root@freebsd:~ # pwd⏎          ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # ls⏎           ▹ディレクトリの中身を確認
.cshrc          .k5login        .login          .shrc
.history        .lesshst        .profile        mybag
root@freebsd:~ # cat .profile⏎ ▹.profile というファイルの内容を表示
省略
root@freebsd:~ # cat .cshrc⏎   ▹.cshrc というファイルの内容を表示
省略
root@freebsd:~ # ▋

何やら謎めいた内容が表示されたことかと思います。 サンプルとして表示させた.profileと.cshrcはシェルにとって特別な役割を持ったファイルです。 その内容はシェルスクリプトと呼ばれるものに近く、プログラミング言語でかかれたコードに近いものです。 今のところはこれ以上シェルについては触れないでおきます。 もし、FreeBSDを使い続けるのであればいつかは確実に学んでおかないといけない科目です。

catに話を戻すと、何やらずらずらと画面に表示されたと思うのですが、一つ大きな問題があります。 画面に収まり切らないとき、ファイルの内容の前の方が流れてしまって目で確認できないことです。 これは致命的です。

画面に収まり切らないファイルの内容を確認するためのものとして、moreとlessというものがあります。 なぜそれを先に取り上げなかったかというと、moreもlessも単純なコマンドとは言えないからです。 何を持って単純でないと言っているかというと、これまでのコマンドは打ち込んだらすぐに画面に結果が表示されて、それでお終い、というものでした。 moreもlessもそうではなく、コマンドを打ち込んだらユーザーからの操作を待ち受ける状態になります。 できればスキップしたかったのですが、 使用頻度はとても高く、無視できそうにもありません。 割と説明が簡単なmoreの操作方法だけ書いておきます。

moreはファイルの内容を閲覧します。 …というのもやはり正確ではありませんが、今の使用目的はそれなのでそうしておきます。 more file1 のようにして、起動します。 そうすると、ファイルの先頭から画面に収まる分だけ表示した状態で待機します。 この状態で特定のキーを押すことでファイルの内容を前後にスクロールしながら内容を見ることができます。 一種のファイルビューアーのようなものと考えてもいいかもしれません。

使用するキーを一覧にしておきます。

キー 動作
スペースキー 一画面先に送る 最後までいったら終了する
q 終了する
f スペースキーと同じ
b 一画面前に戻る
j 一行だけ先に送る
k 一行だけ前に戻る
h ヘルプを表示する

覚え切れなかったら、スペースキーqだけで良いです。

catを解説するはずがだいぶ話がそれてしまいました。 でもこれでファイルの内容は見ることができるようになったはずです。

最後に、catを使用するときに困ったことにならないよう、一つ知っておくべきことを書いておきます。 引数なしで cat と実行すると、コマンドが終了せずプロンプトに戻って来れなくなります。 この状態から抜け出すには Ctrl+d を押します。

6 ファイルやディレクトリをコピーする: cp

ファイルやディレクトリのコピーも日常的に行う作業です。 WindowsやmacOSであるフォルダにあるファイルやフォルダを別のフォルダにコピーした経験はあるかと思います。 cpコマンドで同じようなことができます。 cpの基本は cp コピー元 コピー先 という形です。 一つ目の引数に、コピーしたいもの、二つ目の引数にコピー先です。 単純なようですが、対象がファイルかディレクトリか、コピー先が存在しているかどうか、などで挙動が異なります。 cpはファイルもディレクトリも扱えます。 ファイルの方が分かりやすいので、まずファイルを先に見てみます。

6.1 ファイルをコピーする

最も分かりやすいケースを考えてみます。 カレントディレクトリにあるファイルを、同じ場所に違う名前を与えてコピーする、という場合です。 今rootのホームディレクトリで作業しているとします。 まだファイルを作成する方法を紹介していないので、.profileというファイルを実験用に使いましょう。 このケースでは cp 存在するファイル名 存在しない新しいファイル名 という形になります。

root@freebsd:~ # pwd⏎                ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # cp .profile myfile⏎ ▹.profile というファイルを myfile という名前でコピー
root@freebsd:~ # ls myfile⏎          ▹myfile が作成されたことを確認
myfile
root@freebsd:~ # ▋

コピーした後に、myfileが存在していることを確認して下さい。 catで内容表示させて、まったく同じであることも確認すると良いです。

注意しておきたいのは、コピー先が存在するファイル名だった場合です。 FreeBSDの場合、コピー先に指定された存在していたファイルは上書きされてしまいます。 この挙動は間違いを犯しやすくあまり望ましいものとは思いません。 特に今はrootユーザーで作業しているので、簡単にシステムを壊してしまうことができます。 対策はあるのですが、ここではしません。 ただ注意して使うように心掛けることだけです。

カレントディレクトリ内でしかコピーできないのでは不便なので、もう少し広げてみましょう。 cpは別のディレクトリにあるファイルを、どこでも好きなディレクトリにコピーすることができます。 このケースでは cp 存在するファイルのパス 存在するディレクトリの存在しない新しいファイルのパス という形になります。 ホームディレクトリ実験用のディレクトリを作ってそこにコピーしてみましょう。

root@freebsd:~ # pwd⏎                          ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # mkdir mybox⏎                  ▹コピーを入れておくディレクトリ mybox を作成
root@freebsd:~ # cp /etc/profile mybox/orange⏎ ▹絶対パスと相対パスを使ってファイルをコピー
root@freebsd:~ # ls mybox⏎                     ▹コピーされたか確認
orange
root@freebsd:~ # ▋

catで /etc/profilemybox/orange の内容が同じであることを確認しておくと良いです。

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

もう一つcpのよく使うパターンを見て置きます。 ファイルをコピーするときよくあるのが コピー元のファイルの名前はそのままで、別のディレトリにコピーしたい というケースです。 cpは、コピー先をディレクトリとすることができます。 コピー先がディレクトリの場合、コピー元のファイル名で、そのディレクトリの中にコピーします。 ただし、コピー先のディレクトリは存在していなければなりません。

やってみます。

root@freebsd:~ # pwd⏎                   ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # ls mybox⏎              ▹前に作ったディレクトリの中身を確認
orange
root@freebsd:~ # cp /etc/profile mybox⏎ ▹コピー先にディレクトリを指定してコピー
root@freebsd:~ # ls mybox⏎              ▹コピーされたか確認
orange  profile
root@freebsd:~ # ▋

これは大変便利な振舞いです。 前にちらっと、ドット . と言うディレクトリ名はカレントディレクトリを表している、と述べたことがあります。 ディレクトリ名として . を使うと、別の場所からカレントディレクトリにコピーするのを、短かく入力できます。

root@freebsd:~ # pwd⏎                    ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # cd mybox⏎               ▹作業場所を変更したいので mybox の中に移動
root@freebsd:~/mybox # cp /etc/hosts ./⏎ ▹カレントディレクトリにコピー
root@freebsd:~/mybox # ls⏎               ▹コピーされたか確認
hosts   orange  profile
root@freebsd:~/mybox # ▋

コピー先に指定した ./ のところに注目です。 これがカレントディレクトリを表します。 後ろのスラッシュを付けずに . としても一応大丈夫ですが、ディレクトリであることを強調するために付けています。 このパターンはよく使うので覚えておくと良いです。

次に覚えておくcpのパターンは cp コピー元1 コピー元2 コピー元3 コピー先ディレクトリ のように複数のファイルをまとめて一箇所にコピーするものです。 この形では、最後の引数は必ずディレクトリでなくてはいけません。コピー元のファイルはいくつでも指定できます。

root@freebsd:~/mybox # pwd⏎ ▹現在のディレクトリが前に作った mybox であることを確認
/root/mybox
root@freebsd:~/mybox # cp ../.cshrc ../.history ../.profile ./⏎ ▹まとめてカレントディレクトリにコピー
root@freebsd:~/mybox # ls⏎  ▹コピーされたか確認
.cshrc          .profile        orange
.history        hosts           profile
root@freebsd:~ # ▋

上ではカレンントディレクトリにコピーするために ./ をコピー先としました。 もちろんカレントディレクトリ以外のディレクトリを指定できます。 しかし、コピー先のディレクトリは存在していなければいけません。

6.3 ディレクトリをコピーする

cpはファイルだけでなく、ディレクトリを丸ごとコピーできます。 基本は cp -R コピー元ディレクトリ コピー先ディレクトリ です。 -R オプションが重要です。 コピー先ディレクトリのパスが存在するかしないかによって挙動が異なります。

コピー先のディレクトリが存在しない場合、元のディレクトリを新しい名前のディレクトリでコピーします。

root@freebsd:~ # pwd⏎                ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # ls⏎                 ▹mybox が存在していて mybox2 が存在していないことを確認 
.cshrc          .k5login        .login          .shrc           mybox
.history        .lesshst        .profile        mybag           myfile
root@freebsd:~ # cp -R mybox mybox2⏎ ▹mybox を mybox2 という名前でコピー 
root@freebsd:~ # ls mybox2⏎          ▹mybox2 がコピーされたか中身を表示して確認                
.cshrc          .profile        orange
.history        hosts           profile
root@freebsd:~ # ▋

ls mybox2 でコピーされたmybox2の中身が、元のディレクトリmyboxと同じであることを確認すると良いです。

ただし、コピー先ディレクトリのパスの途中の部分のディレクトリは存在していないといけません。 例えば cp -R mybox aaa/bbb/mybox2 としたとき、aaaとbbbが存在していなければエラーになります。

上ではmyboxの中にはファイルしか含まれていませんでしたが、サブディレクトリを含んでいてOKです。 オプション -R の意味は Recursive です。 ディレクトリの中のディレクトリも、またその中のディレクトリも、またその中のディレクトリも…と繰り返し適用されるのでこれを再帰的と表現します。

root@freebsd:~ # pwd⏎                    ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # mkdir -p mybox/aaa/bbb⏎ ▹コピーするサブディレクトリを作成  
root@freebsd:~ # cp -R mybox mybox3⏎     ▹mybox を mybox3 という名前でコピー 
root@freebsd:~ # ls mybox3/aaa⏎          ▹サブディレクトリ mybox3/aaa/bbb もコピーされていることを確認
bbb
root@freebsd:~ # ▋

ディレクトリに含まれるサブディレクトリも一緒にコピーされたことが確認できました。

次にコピー先のディレクトリが存在する場合です。 この場合は指定されたコピー先のディレクトリの中に、コピーします。

root@freebsd:~ # pwd⏎                    ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # mkdir -p redbox/aaa⏎    ▹コピー先となるディレクトリを作成
root@freebsd:~ # cp -R mybox redbox/aaa⏎ ▹作成したディレクトリに mybox をコピー 
root@freebsd:~ # ls redbox/aaa/mybox⏎    ▹mybox がコピーされたか中身を表示して確認 
.cshrc          .profile        hosts           profile
.history        aaa             orange
root@freebsd:~ # ▋

考え方はファイルの場合と一緒です。

cpはファイルの場合とディレクトリの場合、コピー先が存在する場合としない場合があるので最初は少しややこしく感じられるかもしれません。 どのケースも使用頻度は高く何度も使用することになります。 間違えることも多々あることかと思います。 それを繰り返して身に付けていくしかありません。

7 ファイルやディレクトリを移動する: mv

ファイルやフォルダの移動はWindowsやmacOSだと、ドラッグ&ドロップに近い操作です。 ある場所から、別の場所へアイテムを移動します。 元の場所に移動したものは残りません。 基本は mv 移動元 移動先 という形です。 mv は MoVe の略です。

mvもcpと同じように、ファイルかディレクトリか、移動先が存在するかしないかで挙動が異なってきます。 だいたいcpと同じと考えて良いと思います。 最大の違いは、元のファイルやディレクトリが残らないことです。

7.1 ファイルの移動

ファイルを移動するには mv 元のファイル 移動先 とします。 移動先によっていくつかのケースが考えられます。

  1. 移動先が存在するファイルだった場合、そのファイルは上書きされてしまいます。
  2. 移動先が存在しないファイルだった場合、指定された元のファイルが、移動先として指定された名前になって移動します。 ただし、移動先のパスに含まれる途中のディレクトリは全て存在していなければなりません。
  3. 移動先が存在するディレクトリだった場合、指定された元のファイルの名前まま、移動先として指定されたディレクトリの中に移動します。

ちょっと長いですが1の例です。

root@freebsd:~ # pwd⏎                           ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # mkdir mvhere⏎                  ▹mv の実験用ディレクトリを作成
root@freebsd:~ # cp .profile mvhere/file1⏎      ▹.profile のコピーを file1 という名前で作成
root@freebsd:~ # cat mvhere/file1⏎              ▹コピーしたファイルの内容を確認
省略
root@freebsd:~ # cp .history mvhere/file2⏎      ▹.history のコピーを file2 という名前で作成
root@freebsd:~ # cat mvhere/file2⏎              ▹コピーしたファイルの内容を確認
省略
root@freebsd:~ # mv mvhere/file1 mvhere/file2 ⏎ ▹file1 を file2 に移動
root@freebsd:~ # ls mvhere⏎                     ▹file1 がなくなっていることを確認
file2
root@freebsd:~ # cat mvhere/file2⏎              ▹file2 の内容が file1 に置き換わっていることを確認
root@freebsd:~ # ▋

コピーの場合と同様に、移動先に同名のファイルが存在していても、問答無用で黙って上書きされてしまいます。 -i オプションを付けることで、同名のファイルが存在していたら確認メッセージが表示させるようにすることもできます。 しかし、毎回 mv -i file1 file2 のように指定するのは面倒です。 自動的に -i を付加するようにするにはエイリアスというシェルの機能を使うのが一般的です。 さらに、シェルの起動時に毎回自動でエイリアスを設定するように .login.csrcs のような設定ファイルに記述しておきます。 シェルは別のところで扱いたいので、ここでは具体例はあげないでおきます。 mvする前に、lsでファイルが存在してないことを確認するなどして、注意して使う必要があります。

次に2の例です。

root@freebsd:~ # pwd⏎                   ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # ls mvhere⏎             ▹前の例で作成した実験用ディレクトリの内容を表示して中身を確認
file2
root@freebsd:~ # cp .profile file3⏎     ▹.profile のコピーを file3 という名前で作成
root@freebsd:~ # mv file3 mvhere/file4⏎ ▹file3 を mvhere に file4 という名前で移動
root@freebsd:~ # ls file3⏎              ▹file3 がなくなっていることを確認
ls: file3: No such file or directory
root@freebsd:~ # ls mvhere⏎             ▹mvhere に file4 があることを確認
file2   file4
root@freebsd:~ # ▋

上の例では別ディレクトリに移動させていますが、同じディレクトリ内に別名で移動させるこもできます。

日常の作業でよくあるmvの使い方は、カレントディレクトリで ~mv file1 file2 ~ のようにすることです。 これは実質的にファイル名を変更しているのと同じです。 実際にその目的のために使われます。 mvでファイル名の変更ができるので、ファイル名を変更するというだけのためのコマンド(例えば rename oldname newname のようなコマンド)はUNIX系のOSには用意されていません。 ファイル名を変更したかったらmvを使う、ということは覚えておくと良いです。

次に3の例です。

root@freebsd:~ # pwd⏎               ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # ls mvhere⏎         ▹前の例で作成した実験用ディレクトリの内容を表示して中身を確認
file2   file4
root@freebsd:~ # cp .profile file5⏎ ▹.profile のコピーを file3 という名前で作成
root@freebsd:~ # mv file5 mvhere⏎   ▹file5 を ファイル名は指定せず、ディレクトリ名を指定して移動
root@freebsd:~ # ls file5⏎          ▹file5 がなくなっていることを確認
ls: file5: No such file or directory
root@freebsd:~ # ls mvhere⏎         ▹mvhere に file5 があることを確認
file2 file4 file5
root@freebsd:~ # ▋

ファイルを別ディレクトリに移動させる、という最も直感的な操作がこれにあたります。 ちょうどファイルを別のフォルダにドラッグ&ドロップするのと同じ感じです。

cpと同じように、移動先に指定したのがディレクトリの場合、複数のファイルをまとめて移動することができます。 mv ファイル1 ファイル2 ファイル3 移動先ディレクトリ といった形です。 移動対象のファイルはいくつでも指定できます

7.2 ディレクトリの移動

mvはディレクトリを移動するのにcpのようにオプションをつける必要はありません。 mv 元のディレクトリ 移動先 とします。 移動先によっていくつかのケースが考えられます。

  1. 移動先が存在しているファイルだった場合、エラーで移動に失敗します。
  2. 移動先が存在しないディレクトリだった場合、指定された元のディレクトリが、移動先として指定された名前になって移動します。 ただし、移動先のパスに含まれる途中のディレクトリは全て存在していなければなりません。
  3. 移動先が存在しているディレクトリだった場合、指定された元のディレクトリの名前のまま、指定された移動先のディレクトリの中に移動します
  4. 3の場合で、指定された移動先のディレクトリの中に、指定された元のディレクトリの名前と同名のディレクトリがある場合
    1. 同名のディレクトリが空なら、移動されます。
    2. 同名のディレクトリが空でないなら、エラーとなり失敗します。

ほとんどはファイルと同じ感覚です。

1の例です。

root@freebsd:~ # pwd⏎                  ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # ls mvhere⏎            ▹前の例で作成した実験用ディレクトリの内容を表示して中身を確認
file2 file4 file5
root@freebsd:~ # mkdir mvme⏎           ▹移動対象となるディレクトリを作成
root@freebsd:~ # mv mvme mvhere/file5⏎ ▹ディレクトリを存在しているファイル名に移動を試みる
mv: rename mvme to mvhere/file5: Not a directory
root@freebsd:~ # ▋

ディレクトリを存在しているファイル名に移動しようとしてもエラーとなるため、ディレクトリの移動で間違ってファイルを上書きしてしまうという事態にはなりません。

2の例です。

root@freebsd:~ # pwd⏎            ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # mkdir mvme1⏎    ▹移動させるディレクトリを作成
root@freebsd:~ # mv mvme1 mvme2⏎ ▹mvme1 の移動先に存在しないディレクトリを指定
root@freebsd:~ # ls mvme2⏎       ▹mvme1 が移動されて mvme2 になったこと確認(何も表示されなければ存在している)
root@freebsd:~ # ls mvhere⏎      ▹前の例で作成した実験用ディレクトリの内容を表示して中身を確認
file2   file4   file5
root@freebsd:~ # mv mvme2 mvhere/bad/sad⏎ ▹存在しないディレクトリが含まれるパスを指定して移動を試みる
mv: rename mvme2 to mvhere/bad/sad: No such file or directory
root@freebsd:~ # ▋

感覚的にはファイルの場合と同じように動作するのであまり混乱することはないかと思います。 ファイルの場合と同じように、名前の変更の目的でもよく使われます。

3の例です。

root@freebsd:~ # pwd⏎             ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # ls mvhere⏎       ▹前の例で作成した実験用ディレクトリの内容を表示して中身を確認
file2   file4   file5
root@freebsd:~ # mkdir mvme3⏎     ▹移動させるディレクトリを作成
root@freebsd:~ # mv mvme3 mvhere⏎ ▹mvme3 の移動先に存在するディレクトリを指定
root@freebsd:~ # ls mvhere⏎       ▹mvme3 が mvhere の中に移動されたことを確認
file2   file4   file5   mvme3
root@freebsd:~ # ▋

4の1の例です。

root@freebsd:~ # pwd⏎                   ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # ls mvhere⏎             ▹前の例で作成した実験用ディレクトリの内容を表示して中身を確認
file2   file4   file5   mvme3
root@freebsd:~ # mkdir -p mvme4/sushi ⏎ ▹移動させるディレクトリを作成 確認のためのサブディレクトリを含む
root@freebsd:~ # mkdir mvhere/mvme4 ⏎   ▹移動先に同名となるディレクトリを作成
root@freebsd:~ # mv mvme4 mvhere⏎       ▹移動させる
root@freebsd:~ # ls mvhere/mvme4⏎       ▹移動先の中身を表示して移動されたことを確認
sushi
root@freebsd:~ # ▋

WindowsやmacOSで同じ名前のフォルダが存在するところにフォルダを移動させようとすると、中身を統合するかどうか選択できますが、mvではそうなりません。 その代わりに、空ではないディレクトリを同名のサブディレクトリがあるディレクトリに移動させようとすると、失敗します。 それが4の2です。

root@freebsd:~ # pwd⏎             ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # ls mvhere/mvme4⏎ ▹前の例で作成した実験用ディレクトリの内容を表示して中身を確認
sushi
root@freebsd:~ # mkdir mvme4⏎     ▹移動させる同名のディレクトリを作成
root@freebsd:~ # mv mvme4 mvhere⏎ ▹移動させる
mv: rename mvme4 to mvhere/mvme4: Directory not empty
root@freebsd:~ # ▋

mvは、移動させる MoVe が由来ですが、実際に使用するときの感覚は名前の変更 rename に近いものがあります。

mvは、ファイル名やディレクトリ名を変更するのにも、ディレクトリの構成を変更するため移動させるのにも多用します。 慣れないうちは、名前を変更(rename)しているのか、移動(move)しているのかを意識しながら使うと良いかもしれません。

8 ファイルやディレクトリを削除する: rm

ファイルやディレクトリを作れるようになったのであちこちに作ってると作業場所がちらかってきます。 きれいに保つためには削除することも必要です。 rmコマンドでファイルやディレクトリを削除することができます。 rmは ReMove の略です。

まず知っておかなければいけないことは いったん削除したファイルやディレクトリはもう元に戻すことはできない ということです。 WindowsやmacOSのように、ゴミ箱なるものはありません。 なので、rmコマンドを使うときは、特に今はrootユーザーで作業しているので、慎重に本当に削除していいか考えるようにしてください。 タイプミスにも十分気を付けてください。

8.1 ファイルの削除

ファイルの削除は単純です。 rm ファイル名 とするだけです。 複数のファイルを同時に削除することもできます。 rm ファイル1 ファイル2 ファイル3 といった具合です。

通常は本当に削除してよいかどうかの確認などなく、即削除されます。 オプション -i を付けることで確認の問い合わせメッセージを表示させることができます。 まだ慣れないうちは、指定するようにした方が良いと思うので、ここでは常につけることにします。

実際に使ってみます。

root@freebsd:~ # pwd⏎                     ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # mkdir risky⏎             ▹削除するファイルを入れておくディレクトリを作成
root@freebsd:~ # cp .profile risky/file1⏎ ▹削除する実験用のファイル1
root@freebsd:~ # cp .history risky/file2⏎ ▹削除する実験用のファイル2
root@freebsd:~ # cp .cshrc risky/file3⏎   ▹削除する実験用のファイル3
root@freebsd:~ # rm -i risky/file1⏎       ▹ファイルを一つ指定して削除
root@freebsd:~ # ls risky⏎                ▹file1 が削除されたか確認
file2   file3
root@freebsd:~ # rm -i risky/file2 risky/file3⏎ ▹ファイルを複数指定して削除
root@freebsd:~ # ls risky⏎                ▹file1 と file2 が削除された確認(何も表示がなければOK)
root@freebsd:~ # ▋

rmにはcpやmvのようなややこしいケースはなく、シンプルです。 ただ指定されたものを削除する、それだけです。 削除はリスキーな操作なのでそうあるべきです。

8.2 ディレクトリの削除

ディレクトリを削除するにはrmdirがありました。 rmdirは空のディレクトリしか削除できませんでした。 空でなければ削除できないので安全ではありますが、すべてのサブディレクトリを巡回して、rmで含まれるファイルを削除してからrmdirで削除する、というのは面倒すぎることが多いです。

rmは オプション -r または -R を付けると、ディレクトリを削除することができます。 rは Recursive のことです。 -r-R もどちらを使っても違いはありません。

ファイルを削除するときは -i を付けて確認メッセージを表示させるようにしました。 ディレクトリの場合だと、中に多数のファイルが含まれている場合、すべてのファイルに対して確認メッセージが表示されて、とても煩わしいです。 なので、ディレクトリを削除するときは、逆に確認メッセージを表示させないようにするオプション -f が一緒によく使われます。 例えば rm -rf gomi のようにします。 オプションが複数ある場合は - に続けてまとめることができますので、そうしています。

実際に使ってみます。

root@freebsd:~ # pwd⏎                         ▹現在のディレクトリがrootのホームディレクトリであることを確認
/root
root@freebsd:~ # ls risky⏎                    ▹前回使用したディレクトリが存在することを確認(何も表示されないはず)
root@freebsd:~ # mkdir -p risky/red/pink⏎     ▹サブディレクトリを含めるようにする
root@freebsd:~ # cp .profile risky/file1⏎     ▹ファイルも含めるようにする
root@freebsd:~ # cp .history risky/red/file2⏎ ▹もう一つファイルも含める
root@freebsd:~ # rm -rf risky⏎                ▹空ではないディレクトリ risky を丸ごと削除
root@freebsd:~ # ls risky⏎                    ▹削除されたか確認(存在しないとメッセージが表示されるはず)
ls: risky: No such file or directory
root@freebsd:~ # ▋

rmの使い方はシンプルです。 しかし、それはrmがリスキーなコマンドだからです。 間違いがおこらないようシンプルになっている、はずです。

過去にrmで間違った使い方をして、どれだけの損失がでたのか、統計はありませんがきっと相当なものです。

しかも、今はrootでログインしているので、rm一発ですべてを破壊できます。 rmは本質的に危険だと肝に銘じておくべきです。

だからといって使わないようにするというわけにはいきません。 不要なファイルやディレクトリは削除しないといけません。 ひとつアドバイスをさせてもらうと、rmで削除するときは、特にディレクトリを削除するときは、cdでその対象があるディレクトリに移動してからコマンドを実行するようにすると良いかもしれません。 そうしてrmは常にカレントディレクトリのものを削除するようにします。 コマンドをシンプルに保つことです。

9 まとめ

このページでは、mkdir、rmdir、cat、cp、mv、rm、それとmoreの7つのコマンドを解説しました。 これらのコマンドはごく基本的なもので、極めて使用頻度が高く重要です。 たったこれだけでも、もし最初から順番に読み通してきたならなかなか大変ではなかったかと思います。 実際、書き上げるのは大変でした。

一応、これであとはテキストエディタの使い方を覚えれば、自由にソースコードを書いて、ファイルを管理したりすることができるようになります。 なので、次はテキストエディタについて書きます。 一体いつになったらプログラミングできるんだ‥と思われていることだと思います。 テキストエディタだけやったらその次こそはHello Worldを動かします。

このページのまとめを書いておきます。

  • VirtualBoxのスナップショットを利用すれば、仮想マシンの状態を保存して、あとで復元したりすることが簡単にできるようになります。 リスキーな作業をする前には、スナップショットを作成しておくことお勧めします。
  • mkdirは、ディレクトリを作成します。 オプション -p を付けることで、指定したパスの途中のディレクトリもまとめて作成することができます。
  • rmdirは、ディレクトリを削除します。 ただし、空のディレクトリしか削除できません。
  • catは、ファイルの内容を表示します。 一画面に収まらない場合は、moreを使うとページをスクロールしながら見ることができます。
  • cpは、ファイルやディレクトリをコピーします。 ファイルをコピーする場合、コピー先に同名のファイルが存在していたら上書きされてしまうので注意してください。 ディレクトリをコピーするには -R オプションを付けます。
  • mvは、ファイルやディレクトリを移動します。 名前の変更という目的でも使用します。 ファイルをコピーする場合、移動先に同名のファイルが存在していたら上書きされてしまうので注意してください。
  • rmは、ファイルやディレクトリを削除します。 rmで削除したものは元に戻せません。 十分に注意して慎重に使ってください。 オプション -i を付けると、確認メッセージを表示させるようにすることができます。 ディレクトリを削除するには、オプション -r または -R を使用します。 rm -rf gomi のように使うことが多いです。 ディレクトリが空でなくても削除できます。

著者: watercat

Created: 2023-03-19 日 01:35

Emacs 27.1 (Org mode 9.3)

Validate