Linux の 101 試験対策: ファイルとディレクトリーの管理

Linux のファイルとディレクトリーの操作に慣れる

皆さんもご存知だと思いますが、Linux では何もかもがファイルです。そこで、ファイルとディレクトリーの検索や表示、移動、コピー、アーカイブなど、管理の基礎をしっかり身に付けることが正しい道に踏み出すための一歩となります。この記事の内容は、Linux のシステム管理者として認定するための LPI® 101 試験に備えるためにも、自ら活用するために学ぶ上でも役に立ちます。

Ian Shields, Senior Programmer, IBM

Ian ShieldsIan Shields は、developerWorks Linux ゾーンの様々な Linux プロジェクトに関わっています。彼はノースキャロライナ州 Research Triangle Park にある IBM のシニア・プログラマーです。1973年にオーストラリアのキャンベラでシステム・エンジニアとして IBM に入社して以来、カナダのモントリオールやノースキャロライナ州 Research Triangle Park で、コミュニケーション・システムやパーベイシブ・コンピューティングに携わってきました。彼はいくつかの特許を保持しています。Australian National University にて純粋数学および哲学で学位を取得し、また North Carolina State University にてコンピューター・サイエンスで修士号と博士号を取得しています。Ian について詳しく知るには、My developerWorks で彼のプロフィールを見てください。


developerWorks 貢献著者レベル

2009年 10月 06日

この連載について

この連載は Linux システム管理タスクの学習に役立つだけでなく、LPIC-1 (Linux Professional Institute Certification レベル 1) 試験に備えるための教材にもなります。

連載の各記事についての説明とリンクについては、連載のロードマップを参照してください。現在進行中のこのロードマップは、LPIC-1 試験の最新の目標 (2009年4月) を反映しています。完成した記事はその都度ロードマップに追加されていきますが、当面は developerWorks の LPI 認定試験対策チュートリアルで同様の教材の以前のバージョンを調べてください。これらのバージョンは、2009年4月より前の LPIC-1 目標に対応しています。

前提条件

この連載の記事を最大限に活用するには、Linux の基礎知識と、記事に記載されたコマンドを演習できる実際の Linux システムが必要です。プログラムのバージョンによって出力のフォーマットに違いが出てくる場合もあるため、コマンドの実行結果は必ずしもここに記載するリストや図とまったく同じであるとは限りません。

概要

この記事では、ファイルとディレクトリーの操作に使用する基本的な Linux コマンドの基礎を説明します。この記事で説明する内容は以下のとおりです。

  • ディレクトリーの中身を表示する方法
  • ファイルとディレクトリーをコピー、移動、または削除する方法
  • 複数のファイルおよびディレクトリーを再帰的に操作する方法
  • ワイルドカード・パターンを使用してファイルを操作する方法
  • find コマンドを使用して種類、サイズ、または時刻を基準にファイルを検索し、アクションを実行する方法
  • gzip および bzip2 を使用してファイルを圧縮、解凍する方法
  • tarcpio、および dd を使用してファイルのアーカイブを作成する方法

この記事は、Linux Professional Institute の Junior Level Administration (LPIC-1) 101 試験の主題 103 の 103.2 の試験対策となります。この目標の重要度は 4 です。

ディレクトリーの表示

Linux および UNIX® システムでは、すべてのファイルには、/ をルートとする 1 つの大きなツリー構造のファイルシステムの構成要素としてアクセスします。このツリーにブランチをマウント、アンマウントすることで、ブランチを追加または削除することができます。マウントとアンマウントについては、ファイルシステムのマウントおよびアンマウトに関する今後の記事で説明します (連載のロードマップを参照)。

ディレクトリーの中身の表示

この記事では、記事「Linux の 101 試験対策: テキスト・ストリームとフィルター」で作成したファイルを用いてコマンドの実践演習を行います。手順に従っていれば、ホーム・ディレクトリーに lpi103-2 というディレクトリーが作成されているはずです。このディレクトリーが作成されていない場合は、お使いのシステム上の別のディレクトリーを使って、記事で説明するコマンドの実践演習をしても構いません。

ファイル名とディレクトリー名は、/ で始まる絶対名か、カレント作業ディレクトリーに対する相対名 (つまり / で始まっていない名前) のいずれかとなります。ファイルまたはディレクトリーの絶対パスは、/ の後にディレクトリーが続かない場合もあれば、それぞれに / で区切られた複数のディレクトリーが続く場合もあります。最後はファイル名で終わります。

カレント作業ディレクトリーに相対するファイル名または相対ディレクトリー名を指定する場合には、カレント作業ディレクトリーの絶対名の後に、/ と相対名を連結するだけです。例えば前の記事では、lpi103-2 というディレクトリーを私のホーム・ディレクトリー /home/ian に作成しました。したがって、このディレクトリーのフル・パス (すなわち、絶対パス) は /home/ian/lpi103-2 となります。

カレント作業ディレクトリーの名前は、pwd コマンドを使用して表示することができます。また通常は、PWD 環境変数内でもカレント作業ディレクトリーが有効になります。リスト 1 に pwd コマンドの使い方、そして ls コマンドを使ってディレクトリー内のファイルを表示する 3 通りの方法を記載します。

リスト 1. ディレクトリーの中身の表示
[ian@echidna lpi103-2]$ pwd
/home/ian/lpi103-2
[ian@echidna lpi103-2]$ echo "$PWD"
/home/ian/lpi103-2
[ian@echidna lpi103-2]$ ls
sedtab  text1  text2  text3  text4  text5  text6  xaa  xab  yaa  yab
[ian@echidna lpi103-2]$ ls "$PWD"
sedtab  text1  text2  text3  text4  text5  text6  xaa  xab  yaa  yab
[ian@echidna lpi103-2]$ ls /home/ian/lpi103-2
sedtab  text1  text2  text3  text4  text5  text6  xaa  xab  yaa  yab

上記を見るとわかるように、ls コマンドのパラメーターには相対ディレクトリー名または絶対ディレクトリー名を指定することができます。どちらを指定するとしても、ディレクトリーの中身が表示されます。

詳細の表示

ストレージ・デバイスでは、ファイルまたはディレクトリーは一連のブロックのなかに格納されます。ファイルに関する情報が格納されるのは、i ノードです。ここには、所有者、ファイルの最終アクセス時刻、ファイルのサイズ、ファイルがディレクトリーであるかどうか、ファイルの読み取りまたは書き込みが許可されているユーザーなどの情報が記録されます。i ノード番号はファイル・シリアル番号としても知られており、個々のファイルシステム内でそれぞれに固有です。i ノードに格納される一部の情報は、-l (or --format=long) オプションを使って表示することができます。

ls コマンドはデフォルトでは、名前が (.) ドットで始まる特殊なファイルを表示しません。ルート・ディレクトリー以外のすべてのディレクトリーには、少なくとも 2 つの特殊なエントリーがあります。1 つはディレクトリー自体 (.)、もう 1 つは親ディレクトリー (..) です。ルート・ディレクトリーには親ディレクトリーはありません。

リスト 2 では -l オプションと -a オプションの両方を使用して、. および .. といったディレクトリー・エントリーを含むすべてのファイルを詳細フォーマットで表示しています。

リスト 2. ディレクトリーの中身の詳細表示
[ian@echidna lpi103-2]$ ls -al
total 52
drwxrwxr-x.  2 ian ian 4096 2009-08-11 21:21 .
drwx------. 35 ian ian 4096 2009-08-12 10:55 ..
-rw-rw-r--.  1 ian ian    8 2009-08-11 21:17 sedtab
-rw-rw-r--.  1 ian ian   24 2009-08-11 14:02 text1
-rw-rw-r--.  1 ian ian   25 2009-08-11 14:27 text2
-rw-rw-r--.  1 ian ian   63 2009-08-11 15:41 text3
-rw-rw-r--.  1 ian ian   26 2009-08-11 15:42 text4
-rw-rw-r--.  1 ian ian   24 2009-08-11 18:47 text5
-rw-rw-r--.  1 ian ian   98 2009-08-11 21:21 text6
-rw-rw-r--.  1 ian ian   15 2009-08-11 14:41 xaa
-rw-rw-r--.  1 ian ian    9 2009-08-11 14:41 xab
-rw-rw-r--.  1 ian ian   17 2009-08-11 14:41 yaa
-rw-rw-r--.  1 ian ian    8 2009-08-11 14:41 yab

リスト 2 の最初の行には、表示されたファイルによって使用されているディスク・ブロックの合計数 (52) が示されています。残りの行に示されているのが、各ディレクトリー・エントリーについての情報です。

  • 最初のフィールド (上記の例では drwxrwxr-x または-rw-rw-r--) からは、そのファイルがディレクトリー (d) であるか、通常のファイル (-) であるかがわかります。特殊ファイル (/dev ファイルシステム内のファイルなど) の場合には、シンボリック・リンク (l) やその他の値が示されることもあります。シンボリック・リンクについての詳細は、ハード・リンクとシンボリック・リンクの作成および変更に関する記事で学びます (連載のロードマップを参照)。ファイル・タイプの後には、所有者、所有者のグループ・メンバー、およびその他のユーザーのパーミッションが 3 つずつ続きます (rwx または r-- など)。この 3 つの値は、当該ユーザー、グループ、またはその他のユーザーに読み取り (r)、書き込み (w)、または実行 (x) 権限があるかどうかを示します。setuid などの他の機能の使用方法については、ファイルのパーミッションおよび所有権の管理に関する記事で説明します (連載のロードマップを参照)。
  • 次のフィールドの数字は、ファイルへのハード・リンクの数を示します。前に説明したように、ファイルに関する情報は i ノードに含まれます。ファイルのディレクトリー・エントリーにはそのファイルに対応する i ノードへのハード・リンク (ポインター) が含まれるため、表示されるすべてのエントリーには少なくとも 1 つのハード・リンクがあります。ディレクトリー・エントリーにはさらに、. エントリーのハード・リンクとサブディレクトリー・エントリーごとのハード・リンクもあります。したがってリスト 2 のハード・リンク数 35 で示されているように、.. で表されている私のホーム・ディレクトリーにはかなり多くのサブディレクトリーがあることがわかります。
  • 次の 2 つのフィールドは、ファイルの所有者とその所有者の主グループです。Red Hat や Fedora システムなど、デフォルトでユーザーごとに個別のグループを指定するシステムも一部にありますが、それ例外のシステムでは、すべてのユーザーは 1 つのグループか、おそらくは複数のグループに属します。
  • 次のフィールドは、ファイルの長さをバイト数で示します。
  • 最後から 2 番目のフィールドは、最終変更のタイムスタンプを示します。
  • 最後のフィールドは、ファイルまたはディレクトリーの名前を示します。

ls コマンドの -i オプションは、i ノード数を表示します。i ノードは後で再び登場します。また、ハード・リンクとシンボリック・リンクの作成および変更に関する記事でも、i ノードについて取り上げます (連載のロードマップを参照)。

複数のファイル

ls コマンドには複数のパラメーターを指定することもできます。この場合、指定するそれぞれの名前はファイル名またはディレクトリー名のどちらにすることも可能です。ディレクトリー名を指定すると、ls コマンドはディレクトリー自体の情報ではなく、ディレクトリーの中身を表示します。一方、親ディレクトリーとして表示されている lpi103-2 ディレクトリー・エントリー自体に関する情報が必要な場合には、ls -l ../lpi103-2 コマンドを実行します。すると、前の例と似たような内容が表示されます。リスト 3 に、-d オプションを追加してディレクトリーの中身ではなくディレクトリー・エントリーに関する情報を表示する方法、そして複数のファイルまたはディレクトリーのエントリーに関する情報も表示する方法を示します。

リスト 3. ls -d の使用方法
[ian@echidna lpi103-2]$ ls -ld ../lpi103-2 sedtab xaa
drwxrwxr-x. 2 ian ian 4096 2009-08-12 15:31 ../lpi103-2
-rw-rw-r--. 1 ian ian    8 2009-08-11 21:17 sedtab
-rw-rw-r--. 1 ian ian   15 2009-08-11 14:41 xaa

lpi103-2 の更新時刻が、前のリスト 2 で表示したときの更新時刻とは異なっていることに注意してください。また前のリスト 2 のときとは異なり、lpi103-2 の更新時刻はディレクトリー内のどのファイルのタイムスタンプとも異なります。これが期待される結果かと言えば、通常は違います。しかし、リスト 3 がこうした結果となっている理由は、この記事を作成している間、私はいくつか追加の例を作成し、その後で削除したためであり、ディレクトリーのタイムスタンプがその事実を反映しているというわけです。ファイルの時刻については、「複数のファイルおよびディレクトリーの操作」で詳しく説明します。

出力のソート

デフォルトでは、ls コマンドはファイルをアルファベット順で表示します。出力をソートするためのオプションは、いくつもあります。例えば、ls -t と指定すると更新時刻の順 (時刻が新しい順) にソートが行われ、ls -lS と指定するとサイズの順 (サイズが大きい順) にソートされた詳細な内容が表示されます。さらに -r を追加すれば、ソート順を逆にすることができます。したがって、例えば ls -lrt を実行すると、古い順から新しい順にソートされた詳細な内容が表示されることになります。ファイルおよびディレクトリーを表示するその他の方法については、man ページを参照してください。


ファイルのコピー、移動、削除

ファイルを作成する方法はすでにいくつか説明しましたが、例えばファイルのコピー、ファイル名の変更、ファイルシステムの階層内でのファイルの移動、あるいはファイルの削除を行わなければならないとしたら、どうすればよいでしょうか。その場合には、以下の簡潔な 3 つのコマンドを使用します。

cp
1 つまたは複数のファイルやディレクトリーのコピーを作成するためのコマンドです。このコマンドでは、ソース (すなわちコピー元) の名前を 1 つ (場合によっては複数) とターゲット (すなわちコピー先) の名前を 1 つ指定します。ソースやターゲットの名前にはパスの指定を含めることができます。ターゲットが既存のディレクトリーであれば、すべてのソースがターゲットへコピーされます。ターゲットがまだ存在しない 1 つのディレクトリーの場合には、(単一の) ソースはディレクトリーでなければなりません。この場合、ソース・ディレクトリーとその中身のコピーが作成されて、そのコピーにはターゲットの名前として新しい名前が設定されます。ターゲットが 1 つのファイルであれば、(単一の) ソースも同じくファイルである必要があります。この場合には、ソース・ファイルのコピーが新規に作成され、その新しい名前としてターゲットの名前が設定されます。それと同じ名前を持つ既存のファイルがある場合は新しいファイルで置き換えられます。注意する点として、DOS や Windows オペレーティング・システムでの場合のように、デフォルトでターゲットがカレント・ディレクトリーであるという前提はありません。
mv
1 つ以上のファイルまたはディレクトリーの移動または名前変更を行うためのコマンドです。一般に、使用できる名前は、cp でコピーを作成する場合と同じルールに従います。したがって、単一のファイルの名前を変更することも、ファイルのセットを新しいディレクトリーに移動することもできます。名前は i ノードにリンクするディレクトリー・エントリーでしかないので、ファイルを別のファイルシステムに移動しない限り、i ノードの数が変わらないのは当然です。別のファイルシステムへのファイルの移動は、ファイルをコピーした後に元のファイルを削除するというような動作となります。
rm
1 つ以上のファイルを削除するためのコマンドです。ディレクトリーを削除する方法については、追って説明します。

rename コマンドがない理由

DOS や Windows® システムを使い慣れているとしたら、ファイル名を変更するために mv を使用するのは奇異に感じられるかもしれません。Linux に rename コマンドがあるのは確かですが、DOS や Windows の rename コマンドとは構文が異なります。使用方法についての詳細は、man ページを参照してください。

リスト 4 は、cpmv を使用してサンプル・テキスト・ファイルのバックアップ・コピーを作成する例です。この例では ls -i を使用してファイルの i ノードも表示しています。

  1. まず、text1 ファイルのコピーを text1.bkp として作成しています。
  2. 次に、mkdir コマンドを使用して backup サブディレクトリーを作成しています。
  3. 今度は backup サブディレクトリー内に text 1 ファイルの 2 つ目のバックアップ・コピーを作成し、この 3 つのファイルの i ノードがそれぞれに異なることを確認しています。
  4. text1.bkp を backup ディレクトリーに移動し、その後、移動したファイルの名前を 2 つ目のバックアップの名前に合わせて変更します。この移動と名前変更は 1 つのコマンドで実行することもできますが、ここでは説明のために 2 つのコマンドを使っています。
  5. もう一度 i ノードをチェックし、i ノード番号 934193 を持つ text1.bkp が lpi103-2 ディレクトリー内からなくなっている一方、この i ノードが backup ディレクトリー内にある text1.bkp.1 の i ノードとなっていることを確認します。
リスト 4. ファイルのコピーと移動
[ian@echidna lpi103-2]$ cp text1 text1.bkp
[ian@echidna lpi103-2]$ mkdir backup
[ian@echidna lpi103-2]$ cp text1 backup/text1.bkp.2
[ian@echidna lpi103-2]$ ls -i text1 text1.bkp backup
933892 text1  934193 text1.bkp

backup:
934195 text1.bkp.2
[ian@echidna lpi103-2]$ mv text1.bkp backup
[ian@echidna lpi103-2]$ mv backup/text1.bkp backup/text1.bkp.1
[ian@echidna lpi103-2]$ ls -i text1 text1.bkp backup
ls: cannot access text1.bkp: No such file or directory
933892 text1

backup:
934193 text1.bkp.1  934195 text1.bkp.2

通常、既存のファイルが書き込み可能であれば、cp コマンドはファイルのコピーを既存のファイルに上書きします。その一方、mv コマンドはターゲットが存在する場合にはファイルを移動することも、名前を変更することもしません。cp および mv コマンドのこの動作に関して役に立つオプションには、以下のものがあります。

-f または --force
既存のファイルが書き込み可能でなくても、cp は既存のターゲット・ファイルの削除を行います。
-i または --interactive
既存のファイルを置換する前に確認を求めるようにします。
-b または --backup
ファイルが置換されるときには必ず、そのファイルのバックアップを作成します。

上記のオプションを含め、コピーおよび移動のオプションについての詳細は、例によってman ページを参照してください。

リスト 5 では、バックアップ・オプションを指定してファイルをコピーした後、元のファイルを削除しています。

リスト 5. バックアップ・コピーの作成とファイルの削除
[ian@echidna lpi103-2]$ cp text2 backup
[ian@echidna lpi103-2]$ cp --backup=t text2 backup
[ian@echidna lpi103-2]$ ls backup
text1.bkp.1  text1.bkp.2  text2  text2.~1~
[ian@echidna lpi103-2]$ rm backup/text2 backup/text2.~1~
[ian@echidna lpi103-2]$ ls backup
text1.bkp.1  text1.bkp.2

rm コマンドも -i (対話オプション) と -f (強制オプション) をオプションに指定できることに注目してください。rm を使用してファイルを削除すると、ファイルシステムはそのファイルにアクセスできなくなります。一部のシステムではデフォルトでエイリアスとして alias rm='rm -i' を設定し、root ユーザーが不注意にファイルを削除しないようにしています。誤って削除してしまわないかと心配しているならば、一般ユーザーに対しても対話オプションを使用することが賢明です。

この話題を終える前に 1 つ注意しておく点として、cp コマンドはデフォルトで、新しいファイルに新しいタイムスタンプを作成します。ファイルの所有者とグループは、そのファイルのコピーを実行するユーザーの所有者およびグループに設定されます。選択したファイルの属性を維持したい場合には、-p オプションを使うことができます。ただし、所有権を維持できるユーザーは root ユーザーのみです。詳細については、man ページを参照してください。


ディレクトリーの作成および削除

mkdir を使用してディレクトリーを作成する方法はすでに学んだので、今度は mkdir をさらに掘り下げるとともに、これに類似したコマンドとしてディレクトリーを削除する場合のコマンド、rmdir について説明します。

mkdir

例えばカレント作業ディレクトリーが lpi103-2 ディレクトリーで、その下に dir1 と dir2 というサブディレクトリーを作成したいとします。これまで説明してきたコマンドと同じく、mkdir は複数のディレクトリーの作成要求を 1 回の処理で行うことができます (リスト 6 を参照)。

リスト 6. 複数のディレクトリーの作成
[ian@echidna lpi103-2]$ mkdir dir1 dir2

コマンドが正常に完了しても何も出力されませんが、echo $? を実行すれば、終了コードが本当に 0 であるかどうかを確認することができます。

別の例として、d1/d2/d3 などのネストされたサブディレクトリーを作成しようとしたとします。この場合、d1 および d2 ディレクトリーは存在していないため、コマンドは失敗します。幸い、mkdir には -p オプションがあります。このオプションを使用すれば、必要なすべての親ディレクトリーを作成することができます (リスト 7 を参照)。

リスト 7. 親ディレクトリーの作成
[ian@echidna lpi103-2]$ mkdir d1/d2/d3
mkdir: cannot create directory `d1/d2/d3': No such file or directory
[ian@echidna lpi103-2]$ echo $?
1
[ian@echidna lpi103-2]$ mkdir -p d1/d2/d3
[ian@echidna lpi103-2]$ echo $?
0

rmdir

rmdir コマンドを使用すると、ディレクトリーを作成するのとは逆に、ディレクトリーを削除することになります。このコマンドでも同じく、親ディレクトリーを削除するには -p オプションを使います。rmdir でディレクトリーを削除できるのは、そのディレクトリーが空の場合のみです。これは、このコマンドには削除を強制するオプションがないためですが、再帰的な操作を検討する際に、ディレクトリーが空でなくても削除することができる別の方法を説明します。その方法をいったん覚えたら、コマンドラインで rmdir を使うことはめったになくなると思いますが、それでもこのコマンドについて知っておくと便利です。

ディレクトリーを削除する方法を説明するため、サンプルの text1 ファイルを d1/d2 ディレクトリーにコピーしておきました。したがって、現在このディレクトリーは空ではありません。ここで、mkdir で作成したすべてのディレクトリーを削除するために rmdir を使用します。以下のリストを見るとわかるように、d2 は空でないことから、d1 と d2 は削除されていません。一方、残りのディレクトリーは削除されています。そこで d2 から text1 のコピーを削除すれば、rmdir -p を 1 回呼び出すだけで d1 とd2 を削除することができます。

リスト 8. ディレクトリーの削除
[ian@echidna lpi103-2]$ cp text1 d1/d2
[ian@echidna lpi103-2]$ rmdir -p d1/d2/d3 dir1 dir2
rmdir: failed to remove directory `d1/d2': Directory not empty
[ian@echidna lpi103-2]$ ls . d1/d2
.:
backup  sedtab  text2  text4  text6  xab  yab
d1      text1   text3  text5  xaa    yaa

d1/d2:
text1
[ian@echidna lpi103-2]$ rm d1/d2/text1
[ian@echidna lpi103-2]$ rmdir -p d1/d2

複数のファイルおよびディレクトリーの操作

これまで使用してきたコマンドでは、単一のファイル、あるいは個別に名前がつけられた少数のファイルを操作してきました。記事の残りでは複数のファイルを対象としたさまざまな操作を紹介し、ディレクトリー・ツリーの構成部分の再帰的な操作、そして複数のファイルまたはディレクトリーの保存、復元などを行う方法を説明します。


再帰的な操作

再帰的な表示

ls コマンドには、ディレクトリーとそのすべてのサブディレクトリーを表示する -R (大文字の「R」であることに注意) オプションがあります。この再帰的なオプションが適用されるのは、ディレクトリー名に対してのみです。例えば、ディレクトリー・ツリー内の「text1」という名前のファイルをすべて検出するといった目的では使えません。-R オプションは、これまで説明してきた他のオプションと一緒に使用することができます。リスト 9 に、サンプル lpi103-2 ディレクトリーのサブディレクトリーを i ノード番号と併せて再帰的に表示する例を記載します。

リスト 9. ディレクトリーの中身の再帰的な表示
[ian@echidna lpi103-2]$ ls -iR
.:
934194 backup  933892 text1  933898 text3  933900 text5  933894 xaa  933896 yaa
933901 sedtab  933893 text2  933899 text4  933902 text6  933895 xab  933897 yab

./backup:
934193 text1.bkp.1  934195 text1.bkp.2

再帰的なコピー

cp コマンドを使って、ソース・ディレクトリーまで遡ってその中身を再帰的にコピーするには、-r (または -R、あるいは --recursive) オプションを使用します。無限再帰を防ぐため、ソース・ディレクトリー自体はコピーされません。リスト 10 は、サンプル lpi103-2 ディレクトリーの中身すべてを copy1 サブディレクトリーにコピーする例です。ここではディレクトリー・ツリーの結果を示すために、ls -R を使用しています。

リスト 10. 再帰的なコピー
[ian@echidna lpi103-2]$ cp -pR . copy1
cp: cannot copy a directory, `.', into itself, `copy1'
[ian@echidna lpi103-2]$ ls -R
.:
backup  copy1  sedtab  text1  text2  text3  text4  text5  text6  xaa  xab  yaa  yab

./backup:
text1.bkp.1  text1.bkp.2

./copy1:
text2  text3  text5  xaa  yaa  yab

再帰的な削除

前述したとおり、rmdir が削除するのは空のディレクトリーのみです。そこでリスト 11 に示すように、rm コマンドに -r (または -R、あるいは --recursive) オプションを指定すれば、ファイルディレクトリーの両方を削除することができます。この例では、先ほど作成した copy1 ディレクトリーとその中身を、そこに含まれるバックアップ・サブディレクトリーとその中身を含めて削除しています。

リスト 11. 再帰的な削除
[ian@echidna lpi103-2]$ rm -r copy1
[ian@echidna lpi103-2]$ ls -R
.:
backup  sedtab  text1  text2  text3  text4  text5  text6  xaa  xab  yaa  yab

./backup:
text1.bkp.1  text1.bkp.2

書き込み可能ではないファイルがある場合は、-f オプションを追加して強制的に削除するという方法があります。これは、root ユーザーがクリーンアップの際によく用いる方法ですが、慎重に使用しなければ貴重なデータが失われる可能性があることに注意してください。


ワイルドカードとグロビング

前のセクションの再帰的な操作はツリー全体を対象としましたが、ツリー全体を操作することなく多数のファイルシステム・オブジェクトで単一の操作を行わなければならない場合はよくあります。例えば、それぞれのファイルを表示せずに、lpi103-2 に作成したテキスト・ファイルすべての更新時刻を調べたいというような場合です。この記事のサンプルのような小さなディレクトリーでは簡単なことですが、大規模なファイルシステムともなれば、かなり困難な作業になります。

この問題を解決するには、bash シェルに組み込まれているワイルドカード・サポートを使用します。このサポートは「グロビング (globbing)」とも呼ばれています (当初、/etc/glob という名前のプログラムとして実装されたため)。グロビングでは、ワイルドカード・パターンを使って複数のファイルを指定することができます。

「?」、「*」または「[」の文字が 1 つでも含まれる文字列は、ワイルドカード・パターンです。グロビングとは、シェル (場合によっては別のプログラム) がワイルドカード・パターンを展開し、そのパターンと一致するパス名を表示するプロセスです。マッチングは以下のように行われます。

?
任意の 1 文字と一致します。
*
空の文字列を含め、任意の文字列と一致します。
[
文字クラスを導入します。文字クラスとは空ではない文字列のことで、文字クラスの最後は「]」で閉じられます。この場合の一致とは、この括弧内に含まれる文字と一致することですが、以下に記載するように、特殊な考慮事項がいくつかあります。
  • 「*」および「?」文字は、その文字自体と一致します。これらの文字をファイル名に使用する場合は、適切な引用符で囲むか、エスケープするように考慮してください。
  • 文字列は、空であってはならないと同時に、「]」で終わっていなければならないため、「]」文字そのものと一致させる場合には、これを文字列の先頭に配置しなければなりません。
  • 2 つの文字の間にある「-」は範囲を表します。範囲には、「-」で連結した文字を含め、その 2 つの文字の間にあるすべての文字が照合順序に含まれます。例えば [0-9a-fA-F] は、大文字または小文字の任意の 16 進の数字を表します。「-」を範囲の最初または最後に配置することで、この文字と一致させることができます。
  • 範囲の先頭文字として指定された「!」文字は、その後に続く文字を除くすべての文字と一致するように範囲を補完します。例えば [!0-9] は、0 から 9 の数字を除く任意の文字を意味します。先頭以外の場所にある「!」は、「!」の文字そのものと一致します。「!」はシェルの履歴関数でも使用されるため、この文字を適切にエスケープするように注意してください。

注: ワイルドカード・パターンと正規表現パターンには共通する特徴がありますが、この 2 つは同じではありませんので、十分注意してください。

グロビングは、パス名の構成部分のそれぞれに独立して適用されます。「/」は、一致対象にすることも、範囲内に含めることもできません。例えば lscp、または rm コマンドでは、「/」を任意の場所で使って、複数のファイル名やディレクトリー名を指定することがあるからです。リスト 12 では最初にいくつかの奇妙な名前を付けたファイルを作成し、それからワイルドカード・パターンを使った ls コマンドと rm コマンドを実行しています。

リスト 12. ワイルドカード・パターンの例
[ian@echidna lpi103-2]$ echo odd1>'text[*?!1]'
[ian@echidna lpi103-2]$ echo odd2>'text[2*?!]'
[ian@echidna lpi103-2]$ ls
backup  text1       text2       text3  text5  xaa  yaa
sedtab  text[*?!1]  text[2*?!]  text4  text6  xab  yab
[ian@echidna lpi103-2]$ ls text[2-4]
text2  text3  text4
[ian@echidna lpi103-2]$ ls text[!2-4]
text1  text5  text6
[ian@echidna lpi103-2]$ ls text*[2-4]*
text2  text[2*?!]  text3  text4
[ian@echidna lpi103-2]$ ls text*[!2-4]* # Surprise!
text1  text[*?!1]  text[2*?!]  text5  text6
[ian@echidna lpi103-2]$ ls text*[!2-4] # Another surprise!
text1  text[*?!1]  text[2*?!]  text5  text6
[ian@echidna lpi103-2]$ echo text*>text10
[ian@echidna lpi103-2]$ ls *\!*
text[*?!1]  text[2*?!]
[ian@echidna lpi103-2]$ ls *[x\!]*
text1  text[*?!1]  text10  text2  text[2*?!]  text3  text4  text5  text6  xaa  xab
[ian@echidna lpi103-2]$ ls *[y\!]*
text[*?!1]  text[2*?!]  yaa  yab
[ian@echidna lpi103-2]$ ls tex?[[]*
text[*?!1]  text[2*?!]
[ian@echidna lpi103-2]$ rm tex?[[]*
[ian@echidna lpi103-2]$ ls *b*
sedtab  xab  yab

backup:
text1.bkp.1  text1.bkp.2
[ian@echidna lpi103-2]$ ls backup/*2
backup/text1.bkp.2
[ian@echidna lpi103-2]$ ls -d .*
.  ..

注:

  1. 「*」を併用した補完によって、意外な結果がもたらされることがあります。「*[!2-4]」というパターンは、2、3、または 4 が直後に続かない、名前の構成部分のなかで最も長い部分と一致しますが、このパターンには text[*?!1] と text[2*?!] の両方が該当します。これで、この両方が意外にも一致した理由がわかったはずです。
  2. 前述の ls の例でのように、パターンを展開するとディレクトリー名となる場合、-d オプションが指定されていなければ、そのディレクトリーの中身が表示されることになります (上記の例では、パターン「*b*」の場合)。
  3. ファイル名がピリオド (.) で始まっている場合は、この文字とも明示的に一致しなければなりません。上記では、最後の ls コマンドだけが 2 つの特殊なディレクトリー・エントリー (. および ..) を表示していることに注目してください。

コマンドに含まれるワイルドカード文字はシェルによって展開される可能性が高いため、それによって予期せぬ結果になる場合があることに注意してください。さらに、ファイルシステム・オブジェクトのどれとも一致しないパターンが指定された場合には、POSIX では元のパターン文字列をコマンドに渡すことを要件としていますが、以前の実装の一部ではコマンドに null リストを渡していました。そのため、通常のようには動作しない、かつてのスクリプトに遭遇する場合もあります。リスト 13 に、これらの点をまとめて示します。

リスト 13. ワイルドカード・パターンの予期せぬ結果
[ian@echidna lpi103-2]$ echo text*
text1 text10 text2 text3 text4 text5 text6
[ian@echidna lpi103-2]$ echo "text*"
text*
[ian@echidna lpi103-2]$ echo text[[\!?]z??
text[[!?]z??

グロビングについての詳細は、man 7 glob で調べてください。セクション番号が必要な理由は、セクション 3 でも glob について説明しているためです。さまざまなシェルとの対話のすべてを理解する最善の方法は実践してみることなので、機会があったらいつでもワイルドカードを試しに使ってみてください。cpmv、さらには rm までもが予期せぬ結果をもたらさないように、まずは ls でワイルドカード・パターンを確認することを忘れないようにしてください。


ファイルの時刻の変更

次に取り上げるのは、touch コマンドです。このコマンドでは、ファイルのアクセス時刻と更新時刻を変更することができます。ファイルがない場合は、空のファイルを新規に作成します。このセクションで説明した情報を使ってファイルとディレクトリーを見つける方法については、この次のセクションで紹介します。今回も引き続き、例に用いるのは lpi103-2 ディレクトリーです。このセクションでは、タイムスタンプを指定するさまざまな方法についても説明します。

touch

オプションが指定されていない場合、touch コマンドは 1 つ以上のファイル名をパラメーターとして取り、指定されたファイルの更新時刻を変更します。このタイムスタンプは、ディレクトリーの詳細な表示をしたときに通常表示されるタイムスタンプと同じものです。リスト 14 に、お馴染みの echo コマンドを使って f1 という名前の小さなファイルを作成し、ディレクトリーの詳細表示により、更新時刻 (mtime) を表示する例を記載します。この例では、更新時刻はファイルが作成された時刻と同じになるので、sleep コマンドで 60 秒間待機してから ls コマンドをもう一度実行します。その結果、ファイルのタイムスタンプに 1 分の差が出ていることに注目してください。

リスト 14. touch による更新時刻の更新
[ian@echidna lpi103-2]$ echo xxx>f1; ls -l f1; sleep 60; touch f1; ls -l f1
-rw-rw-r--. 1 ian ian 4 2009-08-14 18:24 f1
-rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 f1

-c または --no-create オプションが指定されていなければ、touch コマンドは指定されたファイル名のファイルが存在しないと自動的に空のファイルを作成します。リスト 15 に、オプションを指定しない場合と指定した場合のコマンドを記載します。作成されているのは、f2 だけであることに注意してください。

リスト 15. touch による空のファイルの作成
[ian@echidna lpi103-2]$ touch f2; touch -c f3; ls -l f*
-rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 f1
-rw-rw-r--. 1 ian ian 0 2009-08-14 18:27 f2

touch コマンドでは、ファイルの更新時刻 (mtime としても知られています) を特定の日付と時刻に設定することもできます。この場合に使用するのは、-d または -t オプションです。-d は、日時形式を極めて柔軟に指定できる一方、-t オプションには少なくとも MMDDhhmm 形式で日時を指定する必要があります。さらにオプションで、年と秒の値を指定することもできます。リスト 16 にいくつか例を示します。

リスト 16. touch での mtime の設定
[ian@echidna lpi103-2]$ touch -t 200908121510.59 f3
[ian@echidna lpi103-2]$ touch -d 11am f4
[ian@echidna lpi103-2]$ touch -d "last fortnight" f5
[ian@echidna lpi103-2]$ touch -d "yesterday 6am" f6
[ian@echidna lpi103-2]$ touch -d "2 days ago 12:00" f7
[ian@echidna lpi103-2]$ touch -d "tomorrow 02:00" f8
[ian@echidna lpi103-2]$ touch -d "5 Nov" f9
[ian@echidna lpi103-2]$ ls -lrt f*
-rw-rw-r--. 1 ian ian 0 2009-07-31 18:31 f5
-rw-rw-r--. 1 ian ian 0 2009-08-12 12:00 f7
-rw-rw-r--. 1 ian ian 0 2009-08-12 15:10 f3
-rw-rw-r--. 1 ian ian 0 2009-08-13 06:00 f6
-rw-rw-r--. 1 ian ian 0 2009-08-14 11:00 f4
-rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 f1
-rw-rw-r--. 1 ian ian 0 2009-08-14 18:27 f2
-rw-rw-r--. 1 ian ian 0 2009-08-15 02:00 f8
-rw-rw-r--. 1 ian ian 0 2009-11-05 00:00 f9

日付を柔軟に表現した場合、それがいつの日付になるのかわからない場合には、date コマンドを使って調べてください。このコマンドでも -d オプションを指定することができ、touch コマンドで指定できるのと同様の形式で指定することができます。

参照ファイル名と併せて -r (または --reference) オプションと使用することで、touch (または date) が既存のファイルのタイムスタンプを使用するように指定することができます。リスト 17 にいくつか例を示します。

リスト 17. 参照ファイルによるタイムスタンプ
[ian@echidna lpi103-2]$ date
Fri Aug 14 18:33:48 EDT 2009
[ian@echidna lpi103-2]$ date -r f1
Fri Aug 14 18:25:50 EDT 2009
[ian@echidna lpi103-2]$ touch -r f1 f1a
[ian@echidna lpi103-2]$ ls -l f1*
-rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 f1
-rw-rw-r--. 1 ian ian 0 2009-08-14 18:25 f1a

Linux システムは、ファイルが更新された時刻と、ファイルがアクセスされた時刻の両方を記録します。この 2 つの時刻はそれぞれ mtimeatime としても知られています。この 2 つのタイムスタンプは、ファイルの作成時には同じ値に設定され、ファイルが変更された時点で両方ともリセットされます。ファイルへのアクセスがあった場合には、ファイルが変更されていないとしても、アクセス時刻が更新されます。touch の最後の例として目を向けるのは、ファイルのアクセス時刻です。アクセス時刻を更新するには、-a (または --time=atime--time=access--time=use) オプションを指定します。リスト 18 では cat コマンドを使用して f1 ファイルにアクセスし、その中身を表示します。次に ls -lls -lu によって、f1 ファイル、そして f1 を参照ファイルとして作成した f1a ファイルの更新時刻とアクセス時刻をそれぞれ表示します。そして最後に touch -a を使用して f1 のアクセス時刻を f1a のアクセス時刻と同じになるように設定し、正しく設定されたことを確認します。

リスト 18. アクセス時刻と更新時刻
[ian@echidna lpi103-2]$ ls -lu f1*
-rw-rw-r--. 1 ian ian 4 2009-08-14 18:39 f1
-rw-rw-r--. 1 ian ian 0 2009-08-14 18:25 f1a
[ian@echidna lpi103-2]$ ls -l f1*
-rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 f1
-rw-rw-r--. 1 ian ian 0 2009-08-14 18:25 f1a
[ian@echidna lpi103-2]$ touch -a -r f1a f1
[ian@echidna lpi103-2]$ ls -lu f1*
-rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 f1
-rw-rw-r--. 1 ian ian 0 2009-08-14 18:25 f1a

許容される時刻と日付の指定方法についての詳細は、touch および date コマンドの man ページまたは info ページを参照してください。


ファイルの検索

ここまでのところで、ファイルとディレクトリーについては、ディレクトリー・ツリー全体を対象とした再帰的な操作と、ディレクトリー・ツリーから選択して操作するグロビングという手法を説明したので、今度は繊細な手段となる find コマンドについて説明します。find コマンドは、名前、タイムスタンプ、サイズなどを基準にして、1 つまたは複数のディレクトリー・ツリー内にあるファイルを検索するためのコマンドです。このセクションの説明でも引き続き、lpi103-2 ディレクトリーを引用します。

find

find コマンドは、完全なファイル名またはファイル名の一部を使用してファイルやディレクトリーを検索するか、あるいはサイズ、種類、ファイルの所有者、作成日、最終アクセス日などを検索基準として検索を行います。最も基本的な find コマンドは、名前または名前の一部による検索です。リスト 19 に、サンプル・ディレクトリー lpi103-2 を使用した例を記載します。この例では、まず、ファイル名に「1」または「k」のいずれかの文字が含まれるすべてのファイルを検索し、次にパス検索をいくつか実行します。パス検索については、リスト 19 の下の注で説明します。

リスト 19. 名前によるファイルの検索
[ian@echidna lpi103-2]$ find . -name "*[1k]*"
./f1a
./f1
./text10
./backup
./backup/text1.bkp.1
./backup/text1.bkp.2
./text1
[ian@echidna lpi103-2]$ find . -ipath "*ACK*1"
./backup/text1.bkp.1
[ian@echidna lpi103-2]$ find . -ipath "*ACK*/*1"
[

注:

  1. 使用できるパターンは、「ワイルドカードとグロビング」で説明したような、シェルのワイルドカード・パターンです。
  2. -name の代わりに -path を使用すると、単なる基本ファイル名ではなく、絶対パスとのマッチングを実行することができます。この場合、パスの一部分だけを対象とした通常のワイルドカード・マッチングとは異なり、パターンにはパスを構成する部分まで含めることが できます
  3. 上記の ipath の使用例に示されているように、find オプションの先頭に「i」を追加すると、文字列またはパターンでの検索で大文字/小文字の違いを無視することができます。
  4. 例えば .bashrc や、カレント・ディレクトリー (.) など、名前がドットで始まるファイルまたはディレクトリーを検索するには、パターンの一部として先頭にドットを指定する必要があります。この指定がないと、名前による検索では、ドットで始まる名前を持つファイルまたはディレクトリーが無視されます。

リスト 19 の最初の例では、複数のファイルと 1 つのディレクトリー (./backup) が検出されました。検索を絞り込むには、-type パラメーターと併せて、種類を表す 1 文字を指定します。検索対象が通常のファイルである場合は「f」、ディレクトリーである場合は「d」、シンボリック・リンクである場合は「l」を使用します。find に使用できるその他の種類については、man ページを参照してください。リスト 20 に、ディレクトリーのみ (-type d) を検索した結果と、ファイル名 (*) も指定して (つまり、この例ではすべてのファイルを指定して) 検索した結果を記載します。

リスト 20. 種類によるファイルの検索
[ian@echidna lpi103-2]$ find . -type d
.
./backup
[ian@echidna lpi103-2]$ find . -type d -name "*"
.
./backup

-type d に何らかの形で名前を指定しなければ、ワイルドカード「*」を使用した場合と同じく、名前の先頭がドットで始まるディレクトリー (この例では、カレント・ディレクトリーにあるディレクトリーのみ) が表示されることに注意してください。

検索基準にはファイル・サイズを使用することもできます。この場合、特定のサイズ (n) のファイルか、または指定した値よりも大きいサイズ (+n)、あるいは小さいサイズ (-n) のファイルを検索します。また、サイズの上限と下限を両方使用すれば、サイズが特定の範囲内のファイルを見つけることもできます。デフォルトでは、find-size オプションで前提とするサイズの単位は、512 バイトのブロックを表す「b」です。これ以外には、バイト単位として「c」、キロバイト単位として「k」を指定することもできます。リスト 21 では、サイズが 0 のすべてのファイルを検索した後、サイズが 24 バイトまたは 25 バイトのすべてのファイルを検索しています。-size0 の代わりに -empty を指定すれば、空のファイルを検索することもできます。

リスト 21. サイズによるファイルの検索
[ian@echidna lpi103-2]$ find . -size 0
./f1a
./f6
./f8
./f2
./f3
./f7
./f4
./f9
./f5
[ian@echidna lpi103-2]$ find . -size -26c -size +23c -print
./text2
./text5
./backup/text1.bkp.1
./backup/text1.bkp.2
./text1

リスト 21 の 2 番目の例では、検索によって返された結果で行うアクションの一例として、-print オプションを指定しています。bash シェルでは、アクションが指定されていない場合、この -print オプションがデフォルトのアクションとなります。一部のシステムやシェルによってはアクションが必須となり、アクションが指定されない場合は何も出力されません。

その他のアクションとしては、ls -lids で出力されるファイル情報に相当する情報を出力する -ls、各ファイルに対してコマンドを実行する -exec などがあります。-exec はセミコロンで終了し、シェルが最初にセミコロンを解釈しないようにエスケープする必要があります。また、find コマンドの実行結果として返されるファイルを -exec で指定されるコマンドで使用する場合は、該当する場所に {} を指定してください。

シェルでは中括弧も意味を持つため、中括弧はエスケープする必要があります (または括弧で囲みます)。リスト 22 に、-ls オプションと -exec オプションを使用してファイル情報を表示する方法を示します。2 番目のフォームでは、i ノード情報が表示されない点に注目してください。

リスト 22. ファイルの検索およびアクションの実行
[ian@echidna lpi103-2]$ find . -size -26c -size +23c -ls
933893    4 -rw-rw-r--   1 ian      ian            25 Aug 11 14:27 ./text2
933900    4 -rw-rw-r--   1 ian      ian            24 Aug 11 18:47 ./text5
934193    4 -rw-rw-r--   1 ian      ian            24 Aug 12 15:36 ./backup/text1.bkp.1
934195    4 -rw-rw-r--   1 ian      ian            24 Aug 12 15:36 ./backup/text1.bkp.2
933892    4 -rw-rw-r--   1 ian      ian            24 Aug 11 14:02 ./text1
[ian@echidna lpi103-2]$ find . -size -26c -size +23c -exec ls -l '{}' \;
-rw-rw-r--. 1 ian ian 25 2009-08-11 14:27 ./text2
-rw-rw-r--. 1 ian ian 24 2009-08-11 18:47 ./text5
-rw-rw-r--. 1 ian ian 24 2009-08-12 15:36 ./backup/text1.bkp.1
-rw-rw-r--. 1 ian ian 24 2009-08-12 15:36 ./backup/text1.bkp.2
-rw-rw-r--. 1 ian ian 24 2009-08-11 14:02 ./text1

-exec オプションは、思い付く限りのさまざまな目的に使用することができます。例えば、以下を見てください。

find . -empty -exec rm '{}' \;

上記によって、ディレクトリー・ツリー内の空のファイルがすべて削除されます。一方、次を実行するとどうなるでしょう。

find . -name "*.htm" -exec mv '{}' '{}l' \;

この場合には、すべての .htm ファイルの名前が .html ファイルに変更されます。

最後に紹介する find の例では、touch コマンドで説明したタイムスタンプを使用して、特定のタイムスタンプを持つファイルを見つけ出します。リスト 23 には、以下の 3 つの例を示します。

  1. -mtime -2を指定すると、find コマンドは過去 2 日間に変更されたすべてのファイルを検出します。この場合の 1 日とは、現在の日時を基準にした 24 時間です。更新時刻ではなくアクセス時刻を基にファイルを見つける場合には、-atime を使用します。
  2. -daystart オプションを追加すると、日数は深夜を基準にしたカレンダー上での日数としてみなされます。この場合には、f6 ファイルがリストから除外されます。
  3. 最後の例では、日数ではなく分単位での時間の範囲を使用し、1 時間前 (60 分) から 10 時間前 (600 分) までに変更されたファイルを検索します。
リスト 23. タイムスタンプによるファイルの検索
[ian@echidna lpi103-2]$ date
Sat Aug 15 00:27:36 EDT 2009
[ian@echidna lpi103-2]$ find . -mtime -2 -type f -exec ls -l '{}' \;
-rw-rw-r--. 1 ian ian 0 2009-08-14 18:25 ./f1a
-rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 ./f1
-rw-rw-r--. 1 ian ian 0 2009-08-13 06:00 ./f6
-rw-rw-r--. 1 ian ian 0 2009-08-15 02:00 ./f8
-rw-rw-r--. 1 ian ian 0 2009-08-14 18:27 ./f2
-rw-rw-r--. 1 ian ian 58 2009-08-14 17:30 ./text10
-rw-rw-r--. 1 ian ian 0 2009-08-14 11:00 ./f4
-rw-rw-r--. 1 ian ian 0 2009-11-05 00:00 ./f9
[ian@echidna lpi103-2]$ find . -daystart -mtime -2 -type f -exec ls -l '{}' \;
-rw-rw-r--. 1 ian ian 0 2009-08-14 18:25 ./f1a
-rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 ./f1
-rw-rw-r--. 1 ian ian 0 2009-08-15 02:00 ./f8
-rw-rw-r--. 1 ian ian 0 2009-08-14 18:27 ./f2
-rw-rw-r--. 1 ian ian 58 2009-08-14 17:30 ./text10
-rw-rw-r--. 1 ian ian 0 2009-08-14 11:00 ./f4
-rw-rw-r--. 1 ian ian 0 2009-11-05 00:00 ./f9
[ian@echidna lpi103-2]$ find . -mmin -600 -mmin +60 -type f -exec ls -l '{}' \;
-rw-rw-r--. 1 ian ian 0 2009-08-14 18:25 ./f1a
-rw-rw-r--. 1 ian ian 4 2009-08-14 18:25 ./f1
-rw-rw-r--. 1 ian ian 0 2009-08-14 18:27 ./f2
-rw-rw-r--. 1 ian ian 58 2009-08-14 17:30 ./text10

find コマンドの man ページを読むと、この簡単な説明では紹介しきれない広範なオプションについて学ぶことができます。


ファイルの識別

ファイル名には、そのファイルに含まれている内容の手掛かりとなる接尾辞 (gif、jpeg、html など) が付いていることがよくあります。Linux ではこのような接尾辞が必ず付いているわけではないため、通常は接尾辞によってファイルの種類を識別することはありません。しかし、処理するファイルのタイプがわかっていれば、そのファイルを表示または操作するために、どのプログラムを使用すればよいのかがわかります。file コマンドは、1 つまたは複数のファイルに含まれるデータの種類を調べるためのコマンドです。リスト 24 に、file コマンドの使用例をいくつか記載します。

リスト 24. ファイルの内容の識別
[ian@echidna lpi103-2]$ file backup text1 f2 ../p-ishields.jpg /bin/echo
backup:            directory
text1:             ASCII text
f2:                empty
../p-ishields.jpg: JPEG image data, JFIF standard 1.02
/bin/echo:         ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically 
linked (uses shared libs), for GNU/Linux 2.6.18, stripped

file コマンドは、3 種類のテストによって各ファイルを分類しようとします。まずファイルシステム・テストでは、stat コマンドの結果を使用して、例えばファイルが空であるか、ディレクトリーであるかを判別します。いわゆるマジック・ナンバー・テストでは、ファイルについて調べ、ファイルの内容を特定します。これらのシグニチャーは、マジック・ナンバーとして知られています。最後に言語テストでテキスト・ファイルの中身を調べ、ファイルが XML ファイルであるか、C または C++ 言語のソース・ファイルであるか、troff のファイルであるか、あるいは何らかの言語プロセッサーのソースとみなされるその他のファイルであるかを判別しようと試みます。このコマンドの実行結果としては、-k または --keep-goingoption が指定されていない限り、最初に検出されたタイプがレポートされます。

file コマンドで使用できるさまざまなオプションについては、man ページで調べることができます。リスト 25 に記載するのは、-i (または--mime) オプションを使用して、ファイルの種類を通常の人間が読み取り可能な出力ではなく、MIME 文字列として表示する例です。

リスト 25. MIME としてのファイルの内容の識別
[ian@echidna lpi103-2]$ file -i backup text1 f2 ../p-ishields.jpg /bin/echo
backup:            application/x-directory; charset=binary
text1:             text/plain; charset=us-ascii
f2:                application/x-empty; charset=binary
../p-ishields.jpg: image/jpeg; charset=binary
/bin/echo:         application/x-executable; charset=binary

マジック・ナンバー・ファイルも、file コマンドによって管理されます。詳細については、man ページを参照してください。

注: 画像ファイルの種類を識別する際には、ImageMagick パッケージに含まれる identify コマンドが詳細情報を提供するための追加ツールとして使用することができます。


ファイルの圧縮

ファイルのバックアップやアーカイブを作成するとき、またはファイルを送信するときには、ファイルを圧縮するのが一般的です。Linux 環境でよく使用される圧縮プログラムには、gzipbzip2 の 2 つがあります。gzip コマンドは Lempel-Ziv アルゴリズムを使用する一方、bzip2 が使用するのは Burrows-Wheeler ブロック・ソート・アルゴリズムです。

gzip と gunzip の使用方法

一般的に、圧縮が効果を発揮するのはテキスト・ファイルです。多くの画像フォーマットはすでにデータを圧縮しているので、画像ファイルやその他のバイナリー・ファイルでは圧縮の効果はそれほどありません。かなり大きなテキスト・ファイルでの圧縮について説明するため、リスト 26 では、これまで使用してきた例のディレクトリーに /etc/services をコピーし、gzip を使って圧縮しています。cp-p オプションを指定しているのは、/etc/servicesのタイムスタンプを維持するためです。圧縮されたファイルは、そのファイル名に .gz という接尾辞が追加されており、タイムスタンプは圧縮前と変わっていないことに注意してください。

リスト 26. gzip による圧縮
[ian@echidna lpi103-2]$ cp -p /etc/services
[ian@echidna lpi103-2]$ ls -l serv*
-rw-r--r--. 1 ian ian 630983 2009-04-10 04:42 services
[ian@echidna lpi103-2]$ gzip services
[ian@echidna lpi103-2]$ ls -l serv*
-rw-r--r--. 1 ian ian 124460 2009-04-10 04:42 services.gz

gzip で圧縮されたファイルを解凍するには、gzip に -d オプションを指定するという方法もありますが、それよりも一般的な方法としては gunzip コマンドを使用します。リスト 27 に示しているのは前者の方法です。解凍されたファイルは、元のファイル名と元のタイムスタンプになっていることに注意してください。

リスト 27. gzip による解凍
[ian@echidna lpi103-2]$ gzip -d services.gz
[ian@echidna lpi103-2]$ ls -l serv*
-rw-r--r--. 1 ian ian 630983 2009-04-10 04:42 services

bzip2 と bunzip2 の使用方法

bzip2 コマンドも、リスト 28 に記載した gzip と同じような方法で扱います。

リスト 28. bzip2 による圧縮
[ian@echidna lpi103-2]$ ls -l serv*
-rw-r--r--. 1 ian ian 630983 2009-04-10 04:42 services
[ian@echidna lpi103-2]$ bzip2 services
[ian@echidna lpi103-2]$ ls -l serv*
-rw-r--r--. 1 ian ian 113444 2009-04-10 04:42 services.bz2
[ian@echidna lpi103-2]$ bunzip2 services.bz2
[ian@echidna lpi103-2]$ ls -l serv*
-rw-r--r--. 1 ian ian 630983 2009-04-10 04:42 services

gzip と bzip2 との違い

設計の上では bzip2 オプションの多くは gzip のオプションと同じですが、この 2 つのコマンドのオプションはまったく同じというわけではありません。上記の 2 つの例で気付いたかもしれませんが、解凍されたファイルの名前とタイムスタンプは元のファイルと同じになります。けれども、圧縮ファイルの名前やタイムスタンプを変更することで、この振る舞いは変えることができます。gzip コマンドでは -N または --name オプションによって名前とタイムスタンプを強制的に維持することができますが、bzip2 にこのようなオプションはありません。また、gzip コマンドには、圧縮ファイルに関する情報を表示する -l オプションがあります。このオプションによって表示される情報には、ファイルが解凍されるときのファイル名も含まれます。リスト 29 に、この 2 つのコマンドの違いをいくつか示します。

リスト 29. gzip と bzip2 との違い
[ian@echidna ~]$ ls -l serv*
-rw-r--r--. 1 ian ian 630983 2009-04-10 04:42 services
[ian@echidna ~]$ gzip -N services
[ian@echidna ~]$ touch services.gz
[ian@echidna ~]$ mv services.gz services-x.gz
[ian@echidna ~]$ ls -l serv*
-rw-r--r--. 1 ian ian 124460 2009-09-23 14:08 services-x.gz
[ian@echidna ~]$ gzip -l services-x.gz
         compressed        uncompressed  ratio uncompressed_name
             124460              630983  80.3% services-x
[ian@echidna ~]$ gzip -lN services-x.gz
         compressed        uncompressed  ratio uncompressed_name
             124460              630983  80.3% services
[ian@echidna ~]$ gunzip -N services-x.gz
[ian@echidna ~]$ ls -l serv*
-rw-r--r--. 1 ian ian 630983 2009-04-10 04:42 services
[ian@echidna ~]$
[ian@echidna ~]$ bzip2 services
[ian@echidna ~]$ mv services.bz2 services-x.bz2
[ian@echidna ~]$ touch services-x.bz2
[ian@echidna ~]$ ls -l serv*
-rw-r--r--. 1 ian ian 113444 2009-09-23 14:10 services-x.bz2
[ian@echidna ~]$ bunzip2 services-x.bz2
[ian@echidna ~]$ ls -l serv*
-rw-rw-r--. 1 ian ian 630983 2009-09-23 14:10 services-x
[ian@echidna ~]$ rm services-x # Don't need this any more

gzipbzip2 はどちらも stdin からの入力を受け付けます。また両方とも、出力を stdout に送信する -c オプションをサポートします。

bzip2 に関連するコマンドは他にも 2 つあります。

  1. bzcat コマンドはファイルを stdout に解凍します。この動作は、bzip2  -dc に相当します。
  2. bzip2recover コマンドは、破損した bzip2 ファイルのデータの復旧を試みます。

gzipbzip2 のその他のオプションについての詳細を学ぶには、man ページが役立ちます。

その他の圧縮ツール

compressuncompress という前からある 2 つのプログラムは、Linux システムと UNIX システムで今でもよく使われています。

また、Linux には Info-ZIP プロジェクトによる zip および unzip コマンドが実装されています。この 2 つのコマンドが提供するプラットフォームに依存しない圧縮機能は、広範なハードウェアおよびオペレーティング・システムで使用することができます。ただし、すべてのオペレーティング・システムが同じファイルの属性またはファイルシステムの機能をサポートするわけではありません。Windows システムで zip 形式の製品ファイルをダウンロードして解凍し、解凍されたファイルを CD や DVD に転送してその製品を Linux にインストールしようとすると、例えば解凍する前の元のファイル・セットに含まれていたシンボリック・リンクが Windows システムではサポートされていないために、インストールの際に問題が発生する場合があります。

上述のプログラムをはじめとする圧縮プログラムについての詳細は、それぞれの man ページを参照してください。


ファイルのアーカイブ

複数のファイルのグループ、あるいはパーティション全体のバックアップを作成するときには、アーカイブを作成するか、もしくは別のユーザーやサイトに送信するために、tarcpio、および dd コマンドが一般に使われています。LPIC レベル 2 認定の一部となっている 201 試験では、バックアップに関して考慮すべき、かなり細かい事項に重点が置かれています。

バックアップの一般的な手法には、以下の 3 つがあります。

  1. 差分 (または累積) バックアップ。最後にフル・バックアップが行われてから変更された内容をすべてバックアップします。リカバリーには、最終のフル・バックアップと最新の差分バックアップが必要になります。
  2. 増分バックアップ。前回の増分バックアップから変更された内容だけをバックアップします。リカバリーには、最終フル・バックアップに加え、最終フル・バックアップ以降のすべての増分バックアップが (順に) 必要になります。
  3. フル・バックアップ。通常はファイルシステム全体、ディレクトリー全体、または関連ファイルのグループ全体を完全にバックアップします。バックアップの作成にかかる時間はフル・バックアップが最も長いため、一般には他の 2 つの手法のいずれか 1 つと一緒に使用されます。

この記事で説明した他のコマンドと併せて、上記のバックアップ・タスクを実行するためのツールとして使えるコマンドを以下に説明します。

tar の使用方法

tar (Tape ARchive に由来) は、入力されたファイルまたはディレクトリーのセットからアーカイブ・ファイル (tarfile または tarball) を作成するコマンドです。tar は、このようなアーカイブからのファイルのリストアも行います。tar の入力にディレクトリーを指定すると、すべてのファイルとサブディレクトリーが自動的に含まれるため、ディレクトリー構造のサブツリーのアーカイブを作成する際には非常に便利です。

出力先はファイルにすることも、テープやディスケットなどのデバイスや stdout にすることもできます。出力先を指定するには -f オプションを使用します。よく使用されるオプションにはこの他、アーカイブを作成する -c、アーカイブを解凍する -x、処理中のファイルの詳細を出力する -v、gzip 圧縮を使用する -z、bzip2 圧縮を使用する -j があります。tar のオプションのほとんどには、ハイフンを 1 つだけ使用するショート・オプションと、2 つのハイフンを使用するロング・オプションがあります。以下の例では、ショート・オプションを使用します。ロング・オプションとその他のオプションについては、man ページを参照してください。

リスト 30 に、tar を使用してサンプル lpi103-2 ディレクトリーのバックアップを作成する方法を示します。

リスト 30. tar による lpi103-2 ディレクトリーのバックアップ
[ian@echidna lpi103-2]$ tar -cvf ../lpitar1.tar .
./
./text3
./yab
...
./f5

通常は、スペースを節約するため、あるいは送信時間を短縮するためにアーカイブ・ファイルを圧縮したいと思うはずです。tar コマンドの GNU バージョンでは、1 つのオプションを指定するだけで、アーカイブ・ファイルを圧縮することができます。そのオプションとは、gzip を使用して圧縮する -z オプションと、bzip2 を使用して圧縮する -b オプションです。リスト 31 に、-z オプションを使用する例と、このオプションを使用しない場合と使用した場合のアーカイブのサイズの差を示します。

リスト 31. gzip による tar アーカイブの圧縮
[ian@echidna lpi103-2]$ tar -zcvf ../lpitar2.tar ~/lpi103-2/
tar: Removing leading `/' from member names
/home/ian/lpi103-2/
/home/ian/lpi103-2/text3
/home/ian/lpi103-2/yab
...
/home/ian/lpi103-2/f5
[ian@echidna lpi103-2]$ ls -l ../lpitar*
-rw-rw-r--. 1 ian ian 30720 2009-09-24 15:38 ../lpitar1.tar
-rw-rw-r--. 1 ian ian   881 2009-09-24 15:39 ../lpitar2.tar

リスト 31 には、tar が持つ別の重要な機能も示されています。この例で使用したのはディレクトリーの絶対パスですが、出力の最初の行から、tar が先行スラッシュをメンバー名から削除していることがわかります。これによりファイルを他の場所にリストアして検証することができるため、システム・ファイルをリストアする場合には特に重要な機能となります。絶対パス名を保存することが必須である場合には、-p オプションを使用してください。また、アーカイブを作成するときには、絶対パス名と相対パス名を混在させないようにすることが得策です。なぜなら、アーカイブからリストアするときには、すべてが相対パスになるからです。

tar コマンドでは、-r または --append オプションを指定するとアーカイブにファイルを追加することができます。これにより、アーカイブに複数のファイルのコピーが含まれることになる場合もありますが、その場合にはリストア操作で最後に操作したファイルがリストアされることになります。複数のファイルのなかから特定のファイルを選択するには、--occurrence オプションを指定します。アーカイブがテープではなく、通常のファイルシステム上にある場合には、-u または --update オプションを指定してアーカイブを更新することができます。これはアーカイブにファイルを追加するような働きをするオプションですが、ただし、アーカイブに含まれるファイルのタイムスタンプをファイルシステム上のファイルと比較し、タイムスタンプが示す時刻がファイルシステム上のファイルの方が新しい場合にだけ追加されるという点が異なります。前述のとおり、このオプションはテープ・アーカイブには機能しません。

tar コマンドでは、アーカイブを現在のファイルシステムと比較して、アーカイブからファイルをリストアすることも可能です。比較を行うには、-d--compare、または --diff オプションを指定します。出力には、ファイルシステムとアーカイブとでコンテンツが異なるファイル、およびタイムスタンプが異なっているファイルが示されます。通常、表示されるのは違いがあるファイルだけですが、前に説明した -v オプションを指定することで、詳細な出力にすることもできます。カレント・ディレクトリーではなく、任意のディレクトリーを指定して、そこから tar に操作を実行させるには、-C または --directory オプションを指定します。

リスト 32 にいくつか例を示します。ここでは touch を使用して f1 ファイルのタイムスタンプを変更した上で tar の比較操作を行い、アーカイブのなかの 1 つから f1 ファイルをリストアしています。説明のため、さまざまな形でオプションを指定しています。

リスト 32. tar による比較およびリストア
[ian@echidna lpi103-2]$ touch f1
[ian@echidna lpi103-2]$ tar --diff --file ../lpitar1.tar .
./f1: Mod time differs
[ian@echidna lpi103-2]$ tar -df ../lpitar2.tar -C /
home/ian/lpi103-2/f1: Mod time differs
[ian@echidna lpi103-2]$ tar -xvf ../lpitar1.tar ./f1 # See below
./f1
[ian@echidna lpi103-2]$ tar --compare -f ../lpitar2.tar --directory /

リストア対象として指定するファイルやディレクトリーは、アーカイブ内での名前と一致していなければなりません。この例では、./f1 ではなく、f1 とだけ指定してリストアしようとしても上手く行きません。グロビングを使用することはできますが、必要以上または必要に満たない数のファイルをリストアすることにならないように注意してください。アーカイブに何が含まれているのかわからない場合には、--list または -t オプションを使用してアーカイブの中身を表示することができます。リスト 33 では、ワイルドカードを指定すると、./f1 以外のファイルもリストアされることになる例です。

リスト 33. tar によるアーカイブの中身の表示
[ian@echidna lpi103-2]$ tar -tf ../lpitar1.tar "*f1*"
./f1a
./f1

find コマンドを使用して、アーカイブを作成する対象のファイルを選択し、その結果を tar にパイプするという手段を使うこともできます。この手法については、cpio の説明のなかで取り上げますが、tar にも適用することができます。

これまで学習してきた他のコマンドと同じく、この簡単な説明では取り上げていないオプションも数多くあるので、詳細は man ページまたは info ページを参照してください。

cpio の使用方法

cpio コマンドは、コピーアウト・モードではアーカイブを作成し、コピーイン・モードではアーカイブをリストアし、コピーパス・モードではファイルのセットをある場所から別の場所にコピーします。コピーアウト・モードには -o または --create オプション、コピーイン・モードには -i または --extractオプション、コピーパス・モードには-p または --pass-through オプションを指定します。入力は、stdin で指定されたファイルのリストです。出力先は stdout、あるいは -f または --file オプションで指定されたデバイスまたはファイルとなります。

リスト 34 に、find コマンドを使用してファイルのリストを生成し、そのリストを cpio にパイプする方法を示します。find-print0 オプションを指定して、ヌルで終了する文字列をファイル名として生成し、cpio には対応する --null オプションを指定して、このフォーマットを読み取るようにしていることに注意してください。こうすることにより、空白や改行文字が組み込まれたファイル名が正しく処理されます。-depth オプションは、find に対し、ディレクトリー名の前にディレクトリー・エントリーを表示するように指定するためのものです。この例ではただ単に、サンプル lpi103-2 ディレクトリーの 2 つのアーカイブを作成しています。1 つは相対名を使用したアーカイブ、もう 1 つは絶対名を使用したアーカイブです。find には、例えば今週変更されたファイルだけを検索するなど、選択されたファイルを絞り込むための多くの機能がありますが、ここでは使用していません。

リスト 34. cpio によるディレクトリーのバックアップ
[ian@echidna lpi103-2]$ find . -depth -print0 | cpio --null -o > ../lpicpio.1
3 blocks
[ian@echidna lpi103-2]$ find ~/lpi103-2/ -depth -print0 | cpio --null -o > ../lpicpio.2
4 blocks

アーカイブが作成されると同時にそのファイルの一覧を表示するには、cpio-v オプションを追加してください。

コピーイン・モード (-i または -extract オプションを指定) での cpio コマンドは、アーカイブの中身を表示することも、選択されたファイルをリストアすることもできます。ファイルを表示する場合には、--absolute-filenames オプションを指定すると、パスに先行 / 文字がある場合にはこれを削除するため、古いバージョンの cpio が発行するような無関係なメッセージの数を減らすことができます。このオプションは、現行の実装の多くでは自動的に無視されます。リスト 35 に、先ほどのアーカイブを選択的に表示した場合の出力を記載します。

リスト 35. cpio による選択されたファイルの表示およびリストア
[ian@echidna lpi103-2]$ cpio  -i --list  "*backup*" < ../lpicpio.1
backup
backup/text1.bkp.1
backup/text1.bkp.2
3 blocks
[ian@echidna lpi103-2]$ cpio  -i --list absolute-filenames "*text1*" < ../lpicpio.2
/home/ian/lpi103-2/text10
/home/ian/lpi103-2/backup/text1.bkp.1
/home/ian/lpi103-2/backup/text1.bkp.2
/home/ian/lpi103-2/text1
4 blocks

リスト 36 は、パスに「text1」が含まれるすべてのファイルを一時サブディレクトリーにリストアする例です。該当するファイルの一部は、サブディレクトリーに置かれています。tar とは異なり、ディレクトリー・ツリーが存在しない場合には、-d または --make-directories オプションを明示的に指定する必要があります。さらに、ファイルシステム上のファイルがアーカイブ・コピーよりも新しい場合は、-u または --unconditional オプションを指定しない限り、cpio はファイルシステム上のファイルを置換しません。

リスト 36. cpio による選択されたファイルのリストア
[ian@echidna lpi103-2]$ mkdir temp
[ian@echidna lpi103-2]$ cd temp
[ian@echidna temp]$ cpio  -idv "*f1*" "*.bkp.1" < ../../lpicpio.1
f1a
f1
backup/text1.bkp.1
3 blocks
[ian@echidna temp]$ cpio  -idv "*.bkp.1" < ../../lpicpio.1
cpio: backup/text1.bkp.1 not created: newer or same age version exists
backup/text1.bkp.1
3 blocks
[ian@echidna temp]$ cpio  -id --no-absolute-filenames "*text1*" < ../../lpicpio.2
cpio: Removing leading `/' from member names

4 blocks
./home/ian/lpi103-2/backup/text1.bkp.1
./home/ian/lpi103-2/backup/text1.bkp.2
./home/ian/lpi103-2/text1
./backup/text1.bkp.1
[ian@echidna temp]$ cd ..
[ian@echidna lpi103-2]$ rm -rf temp # You may remove these after you have finished

その他のオプションについての詳細は、man ページを参照してください。

dd コマンド

dd コマンドは突き詰めるところ、入力ファイルを出力ファイルにコピーするコマンドです。ファイルをコピーするには cpコマンドを使用できるというのに、さらに別のコマンドがあるのは不思議に思うかもしれませんが、dd コマンドは通常の cp コマンドにはない機能がいくつかあります。具体的に言うと、まずこのコマンドではファイルの変換をすることができます。例えば、小文字から大文字への変換、ASCII から EBCDIC への変換などです。また、ファイルをテープに転送する場合に理想的な機能として、ファイルを再ブロック化することも可能で、ファイルの選択されたブロックだけをスキップまたは組み込むことができます。そして最後に、このコマンドは /dev/sda などの RAW デバイスに対する読み取り、書き込みの操作を行えるため、それ自体が完全なパーティション・イメージであるファイルを作成したり、リストアしたりすることもできます。デバイスへの書き込みには、通常 root 権限が必要です。

まず単純な例として、conv オプションを指定してファイル内のテキストを大文字に変換する方法をリスト 37 に示します。この例では、デフォルトの stdin を使用する代わりに、if オプションによって入力ファイルを指定しています。これと同じようなオプションには、出力先をデフォルトの stdout から別の出力先へを変更する of オプションもあります。説明のため、ibs および obs オプションを使用して異なる入力ブロック・サイズと出力ブロック・サイズを指定しました。ファイルのサイズが大きい場合には、このオプションを使って大きなブロック・サイズを指定すれば、ディスク間でのファイル転送中の処理速度を短縮できるので重宝します。ディスク間でのファイル転送以外では、ブロック・サイズは主に磁気テープで使用されます。以下のリストの最後の 3 行のステータス行には、完全に読み書きされたブロック数、部分的に読み書きされたブロック数、そして転送されたデータの合計量が示されていることに注意してください。

リスト 37. dd によるテキストの大文字への変換
[ian@echidna lpi103-2]$ cat text6
1 apple
2 pear
3 banana
9       plum
3       banana
10      apple
1 apple
2 pear
3 banana
9       plum
3       banana
10      apple
[ian@echidna lpi103-2]$ dd if=text6 conv=ucase ibs=20 obs=30
1 APPLE
2 PEAR
3 BANANA
9       PLUM
3       BANANA
10      APPLE
1 APPLE
2 PEAR
3 BANANA
9       PLUM
3       BANANA
10      APPLE
4+1 records in
3+1 records out
98 bytes (98 B) copied, 0.00210768 s, 46.5 kB/s

入力ファイルと出力ファイルのいずれにしても、RAW デバイスにすることができます。通常、入力または出力ファイルに RAW デバイスを使用するのは磁気テープの場合ですが、ディスク・パーティション全体 (/dev/hda1、/dev/sda2 など) をファイルまたはテープにバックアップすることも可能です。バックアップ中にデータが変更されないように、デバイス上のファイルシステムはアンマウントされていることが理想的です。あるいは少なくとも、読み取り専用でマウントされていなければなりません。リスト 38 の例では、入力ファイルが RAW デバイス (dev/sda2) で、出力ファイルが root ユーザーのホーム・ディレクトリーに置かれている backup-1 ファイルです。ファイルをテープまたはフロッピー・ディスクにダンプするには、of=/dev/fd0、または of=/dev/st0 のように指定することになります。

リスト 38. dd によるパーティションのバックアップ
[root@echidna ~]# dd if=/dev/sda2 of=backup-1
1558305+0 records in
1558305+0 records out
797852160 bytes (798 MB) copied, 24.471 s, 32.6 MB/s

上記からわかるように、797,852,160 バイトのデータがコピーされたため、出力ファイルは実に大きいものになっています。しかしこの特定のパーティションのうち、実際に使用されるのは約 3 パーセントでしかありません。そこで、ハードウェア圧縮を使用してテープにコピーするのでない限り、データを圧縮したいと思うはずです。リスト 39 に、そのための dd コマンドの実行方法の 1 つを示すとともに、lsX および df コマンドを実行することで、この dd コマンド実行後のファイル・サイズと /dev/sda2 上のファイルシステムの使用率を表示します。

リスト 39. dd による圧縮を使用したバックアップ
[root@echidna ~]# dd if=/dev/sda2 |gzip >backup-2
1558305+0 records in
1558305+0 records out
797852160 bytes (798 MB) copied, 23.4617 s, 34.0 MB/s
[root@echidna ~]# ls -l backup-[12]
-rw-r--r--. 1 root root 797852160 2009-09-25 17:13 backup-1
-rw-r--r--. 1 root root    995223 2009-09-25 17:14 backup-2
[root@echidna ~]# df -h /dev/sda2
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda2             755M   18M  700M   3% /grubfile

gzip 圧縮によって、ファイル・サイズは圧縮されていない場合の約 20% にまで縮小されました。ただし、使用されていないブロックにも何らかのデータが含まれている可能性があるため、圧縮されたバックアップでさえも、パーティション上のデータの合計を遙かに上回る大きさになる場合があります。

コピーされた合計バイト数を、処理したレコードの数で割ると、dd が 512 バイトのデータ・ブロックに書き込みを行っていることがわかります。テープなどの RAW 出力デバイスにコピーする場合、これではかなり非効率的な操作になってしまします。そのような場合には、前述したように、obs オプションを指定して出力サイズを変更するか、ibs オプションを使用して入力ブロック・サイズを指定してください。bs とだけ指定して、入力ブロック・サイズと出力ブロック・サイズの両方を同じ値にすることもできます。テープを使用するときには、テープへの書き込みに使用したブロック・サイズと同じブロック・サイズでテープを読み取る必要があります。

バックアップを保存するために複数のテープ、またはその他のリムーバブル・ストレージが複数必要な場合には、split などのユーティリティーを使用してバックアップを分割しなければなりません。ディスクまたはテープのラベルなどのブロックをスキップする必要がある場合は、dd を使用してスキップすることができます。その方法については、man ページの例を参考にしてください。

dd コマンドはファイルシステムを認識しないため、ファイルシステム上に何があるのかを調べるには、パーティションのダンプをリストアしなければなりません。リスト 40 は、リスト 39 でダンプされたパーティション、/dev/sdc7 をリストアする例です。このパーティションは、この例を説明するためだけに、リムーバブル USB ドライブに作成したものです。

リスト 40. dd によるパーティションのリストア
[root@echidna ~]# gunzip backup-2 -c | dd  of=/dev/sdc7
1558305+0 records in
1558305+0 records out
797852160 bytes (798 MB) copied, 30.624 s, 26.1 MB/s

興味深い点として、一部の CD/DVD 作成アプリケーションは表面下で dd コマンドを使用して実際のデバイス書き込みを行っています。お使いのユーティリティーが実際に使用されたコマンドのログを作成しているとしたら、そのログを調べてみると dd についてさらに知る上で参考になるはずです。ISO イメージを CD または DVD ディスクに焼く場合、エラーが発生していないことを確認する 1 つの方法は、まさにこの dd を使用してイメージを焼いた後のディスクを読み取り、その結果を cmp ユーティリティーを使用してパイプすることです。その一般的方法として、ISO イメージの代わりにこの記事で作成したバックアップ・ファイルを使用した例をリスト 41 に示します。読み取るブロックの数を計算するために、イメージのファイル・サイズを使用していることに注意してください。

リスト 41. イメージとファイルシステムとの比較
[root@echidna ~]# ls -l backup-1
-rw-r--r--. 1 root root 797852160 2009-09-25 17:13 backup-1
[root@echidna ~]# echo $(( 797852160 / 512 )) # calculate number of 512 byte blocks
1558305
[root@echidna ~]# dd if=/dev/sdc7 bs=512 count=1558305 | cmp - backup-1
1558305+0 records in
1558305+0 records out
797852160 bytes (798 MB) copied, 26.7942 s, 29.8 MB/s

参考文献

学ぶために

製品や技術を入手するために

  • developerWorks から直接ダウンロードできる IBM 試用版ソフトウェアを使用して、Linux で次の開発プロジェクトを構築してください。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux
ArticleID=442429
ArticleTitle=Linux の 101 試験対策: ファイルとディレクトリーの管理
publish-date=10062009