Linuxコマンド・bashの使い方実例

Linuxコマンド・bashの使い方の実例を紹介します。
管理人は某企業で、一応SEとして働かせていただいております(本業は組み込み系)。
まだまだ未熟者ですが、皆さんのお役に立てたら幸いです。

カテゴリ: Linuxコマンド

Linux環境での圧縮・解凍コマンドをまとめました。
圧縮プログラムが多いので、忘れやすいですよね。

※以下の表はディレクトリごと圧縮する場合を想定して記載しています。

拡張子ごとの圧縮方法と解凍方法まとめ表
拡張子圧縮方法解凍方法
.zipzip -r target.zip target/unzip target.zip
.tartar -cvf target.tar target/tar -xvf target.tar
.gz .tar.gz .tgztar -cvzf target.tgz target/tar -xvzf target.tgz
.xz .tar.xztar --xz -cvf target.tar.xz target/tar --xz -xvf target.tar.xz
.bz2 .tar.bz2 .tbztar -cvjf target.tbz target/tar -xvjf target.tbz
.lz .tlztar --lzip -cvf target.tlz target/ (*1)tar --lzip -xvf target.tlz

*1 以下のようなエラーが発生した場合、
 lzipがインストールされていない可能性があります。
 tar (child): Error is not recoverable: exiting now
 lzipをインストールする方法:sudo apt-get install lzip

■解説
zip以外はtarコマンドを使います。
zipの-rオプションは、ディレクトリを圧縮する場合に指定します。
以下はtarコマンドのオプションの説明です。
-c 圧縮する場合に指定します。(createのcと覚えましょう)
-x 解凍する場合に指定します。(extractのxと覚えましょう)
-v 情報を出力します。指定しなくても動作します。
-f 後続のファイルが圧縮ファイル名示します。ファイル名の直前でなければなりません。順番をいれかえると意図しない動作になるため注意(例えば-cfvにすると、vという名の圧縮ファイルが生成されます)。
-z gzipプログラムで圧縮する場合に指定します。
--xz(または-J) xzプログラムで圧縮する場合に指定します。
-j bzip2プログラムで圧縮する場合に指定します。
--lzip lzipプログラムで圧縮する場合に指定します。

■(参考)圧縮サイズ比較
全てテキストファイルで構成されるディレクトリを圧縮した場合、
(バイナリの場合はまた結果は変わってくると思うので、参考までに)
結果は以下となりました。
最もサイズが小さいのは、tbz(gzip2)でした。

   273  8月 30 22:45 target.tbz
   289  8月 30 22:49 target.tlz
   294  8月 30 22:44 target.tgz
   316  8月 30 22:44 target.xz
  1331  8月 30 23:02 target.zip
 10240  8月 30 23:02 target.tar



スポンサードリンク
スポンサードリンク

業務では、あるファイルに対する変更を、別のファイルにも適用する機会が多くあります。
こういった単純作業は、自動化して(パッチを当てて)一瞬で終わらせてしまいましょう。

ここでは、diffコマンドで作成したパッチを、patchコマンドで適用する方法を紹介します。


■パッチ(差分ファイル)を作成する

diff -ru [変更前ディレクトリ] [変更後ディレクトリ] > patch_work

解説:
変更前にディレクトリごとバックアップをとっておいたことを前提として、
ディレクトリ単位で差分patch_workに出力します。

rオプションは、サブディレクトリに含まれるファイルも再帰的に比較するために指定します。

uオプションは、差分をユニファイドdiff形式で出力するために指定します。

patch_workにリダイレクト(>)で出力していますが、ファイル名は何でも構いません。


■パッチを当てる

patch -u  -p 1 -d [パッチを当てるディレクトリ] < patch_work

解説:
uオプションはユニファイドdiff形式のパッチを当てる場合に指定します。

pオプションは、パッチファイルに記載されているファイルパスの階層を無視する数を指定します。

この例だと、-p 1と指定しているため、パッチファイルに記載されているファイルパスが
src_dir/test.txt と記載されている場合、1階層分のsrc_dirが無視され、
カレントディレクトリにあるtest.txtとしてpatchコマンドは認識します。

pオプションを指定する理由は、次のdオプションを使うためです。

dオプションの意味は、
「指定されたディレクトリへ移動してpatchコマンドを実行する」という意味です。

このように、pオプションとdオプションを組み合わせることで、
パッチに記載されているディレクトリ名と、パッチを当てたいディレクトリ名が異なる場合でも、パッチを当てることができます。
少しわかりにくいかもしれませんが、実際にコマンドを実行してみると理解できると思います。

patchコマンドを実行すると、SuccessやFailerなどの文字が出力されます。
これは、パッチが正しく「当たった」か、「当たらなかった」かを表しています。
パッチが「当たらなかった」時は、当たらなかったファイルの同階層に、
.rej拡張子のファイルが出力されます(ファイルの検索は目視ではなくfindコマンドを使用しましょう)。
このファイルに、当たらなかった差分が出力されているので、
手動でその差分を目的のファイルにマージしてください。

なお、パッチが「当たらない」場合とは、
パッチに記載されている差分の前後3行に一致する行が無かった場合か、
逆に一致する行が複数あってどこに当てるべきか判断できない場合などです。
対処として、パッチの作成時に前後の出力する行数をUオプションなどで調整したりします。


解説は以上です。
私の説明が下手でわかりにくいかもしれませんが、
たった2つのコマンドしか実行していません。

非常によく使う、強力なコマンドですので、
Linuxを使う方はぜひ活用し、作業を効率化しましょう。

findコマンドを実行すると、ファイルのリストを取得することができます。
これを他のコマンドに渡すには、execオプションを指定します。

■実行例
find . -name "*.txt" -exec touch {} \;

■解説
上記を実行すると、
カレントディレクトリ以下を再帰的に検索し、
.txt拡張子ファイルタイムスタンプを現在時刻へ変更します。

-execの後には、findコマンドの結果に対して行うコマンドを指定します。
例の場合、タイムスタンプを現在時刻へ変更するtouchコマンドを指定しています。
この時、findコマンドの実行結果は、{}の箇所に入ります。
{}を入れるのを忘れるとエラーになります。意外と忘れやすいので注意しましょう。

-execで指定するコマンドの最後に、セミコロン(;)を入れる必要があります。
しかしそのままセミコロンを入れると、コマンドを続けて実行するセミコロンの意味と重複してしまいます。
そのため、バックスラッシュまたは円マークで、エスケープする必要があります。

以下はexecオプション以外の部分の解説です。

findの直後は検索を開始するディレクトリを指定します。
例では、カレントディレクトリ(.)を指定しています。

-nameオプションは、検索対象のファイル名を指定します。
例ではワイルドカード(*)の正規表現を用いて、
ファイル名の最後が.txtであるファイルを検索対象としています。

■補足
findコマンドでよく使うオプションを紹介します。

-mindepth
 結果に出力する最小階層数を指定します。
-mindepth 1とすると、実行結果に出力される、検索開始ディレクトリ自体(.等)を除外することができます。

-maxdepth 結果に出力する最大階層数を指定します。
-mindepthの逆の使い方です。
-mindepthと組み合わせて、-mindepth 1 -maxdepth 1とすると、カレントディレクトリのみを検索対象とすることができます。

-type 検索対象のファイルタイプを指定します。
-type f とすると、ファイルのみを検索対象にします。
-type d とすると、ディレクトリのみを検索対象にします。
他の種類も指定できるので、詳しく知りたい方は--helpやman findで確認してください。


解説は以上です。
今回説明した内容は、どれも非常によく使うので、
Linuxコマンドを使う方は、何も見ずに実行できるようにしておきましょう。
作業がとても効率化します。

patchコマンドで差分をマージするときなんかは、diffコマンドの結果はそのまま使えますが、
人が見るとき(主に業務でのレビュー時など)は、1つのファイルに差分が全部出力されると見辛いことがあります。

そこでディレクトリを再帰的に比較し、ファイルごとに差分を出力するスクリプトを作ってみました。
(参考:再帰的にdiffを取って1つのファイルに出力する方法はこちらを参照


■スクリプト(本体)
スクリプトのダウンロード

■スクリプトの実行方法
./diff_dir.sh [変更前ディレクトリ] [変更後ディレクトリ]

■スクリプトの説明
このスクリプトは、ディレクトリ指定で差分を取ることができ、
出力する差分は差分のあるファイルごとに出力されます。

差分を出力するディレクトリは、このスクリプトを実行した時のカレントディレクトリに、「DIFF_output」というディレクトリを作成し、そこに出力します。
この出力先のディレクトリが既にある場合、削除して作り直します。

出力するファイル名は、比較したファイル名に「_DIFF.txt」を付加して出力します。
子ディレクトリに含まれるファイルは、「ディレクトリ名_...」を付加して出力します(処理的には、ファイルパスに含まれるスラッシュをアンダーバーに変換する)。

出力先には、「DIFF_report.txt」というファイル差分の有無だけを出力したファイルを出力します。
ファイルの追加、削除などはこれを参照して確認できます。

■実行時の注意
このスクリプトはbashなどのBシェル系の文法で記載しているため、
/bin/sh が /bin/csh へのリンクになっている環境では、構文エラーになります。
その場合は、1行目(シェバング行と呼ばれ、スクリプトを読むインタプリタを指定する行)を、
#!/bin/bash へ変更してください。


説明は以上ですが、上記で使われている固定値(出力先ディレクトリ名など)は、
スクリプトを編集して自分なりに使ってみてください。

近いうちこのスクリプトの解説も行いたいと思います。

if文を書くほどでもない、ちょっとした条件分岐処理を行う場合、便利な方法があります。
以下のように実行します。

■ホームディレクトリにtmp3フォルダまたはファイルが無ければNot existと出力し、最後にENDと出力するコマンド
test -e ~/tmp3 || echo 'Not exist' ; echo 'END'

上記の「||」は、
直前の実行結果(echo $?の値)が真(0)であれば直後のコマンドは実行しません。
直前の実行結果が偽(非0)であれば直後のコマンドを実行します。
「;」は、直後のコマンドを(条件関係無く)連続して実行します。

これを利用することで、if文を使わなくとも、条件分岐を行うことができます。
シェルなどのスクリプトだけでは無く、コマンドラインでも使えるので、汎用性が高いです。

ちなみに、上記コマンド例のtestコマンドの実行結果を否定させることで、
「tmp3ディレクトリがあれば、実行する」とすることも可能です。

■ホームディレクトリにtmp3フォルダまたはファイルがあればExistと出力し、最後にENDと出力するコマンド
test ! -e ~/tmp3 || echo 'Exist' ; echo 'END'

また、「||」を複数使うことで、複数の条件をつけることも可能です。

■ホームディレクトリにtmp2、tmp3の両方が無ければNot existと出力、どちらかがあれば何も出力せず、最後にENDと出力するコマンド
test -e ~/tmp2 || test -e ~/tmp3 || echo 'Not exist' ; echo 'END'


要は、論理演算のorなんですよね。前のコマンドから順番に評価し、実行結果が真になったら、以降の評価はせずに、次のコマンドへ進む。
これらの構文を利用して、スクリプトを簡潔に記載したり、コマンドライン操作を効率化しましょう!
(ちなみに私はこの構文を忘れることが多いので、備忘録も兼ねて記事にさせていただきました。)
ただし、スクリプトで多用しすぎると、可読性が低くなることがありますので、
複雑な条件分岐で使うのは避けた方が良いでしょう。その場合は素直にif文を使った方が良いですね。 

↑このページのトップヘ