いくつ知っている?時間の無駄を減らすLinuxコマンドのおすすめ3選
2021.11.05
Linuxコマンドはオプションも含めると種類が多く、全てを使いこなすことはとても大変です。ある日出会ったコマンドに今までの作業が1行で集約できることに気づき、感動することもあるでしょう。
本記事では筆者が感動した、作業時間を短縮できるLinuxコマンドを3つご紹介します。
はじめに
Linuxコマンドはオプションも含めると非常に種類が多いものです。 普段から使用している人も、実はあまり使い方がわからないコマンドも多く存在するのではないのでしょうか。しかしコマンドを知らないがために、実は無駄に作業量が増えている可能性があるかもしれません。私は、ある日あるコマンドに出会ったことで開発効率がぐんと上がって感動したこともありました。
そこで今回は、エンジニアが時間を無駄にしないために絶対知っておくべきコマンドを3つ紹介させていただきます。問題を3問出題した後、解説と便利ポイントを紹介する形となっています。みなさんはいくつ知っているでしょうか。
Linuxコマンドを知らないと時間が無駄になる理由
問題の前に、なぜ、コマンドを知らないと時間が無駄になるのでしょうか。 その理由は、コマンドを知らない人は、知っている人に比べて作業時間がより多くかかるからです。私の場合、作業中に効率が悪いと考えている時は、たいていコマンドを組み合わせて頑張ることで、作業効率が改善することも多いです。
例をあげましょう。以下のタスクに対して、どう作業しますか?
「このディレクトリ以下にある、”Hello” と書かれたファイルを全て見つけ、”Goodbye”に変換してください」
あるコマンドを知っている方なら、1行のコマンドで実行できます(記事の後方で紹介します)。そのコマンドを使用しない場合でも何行かで実現できる方法はあるでしょう。何もコマンドを知らない方はメモ帳などのエディタでいくつあるかわからない数のファイルを全て開き、手打ちで変換を行うしかありません。
これをみると作業量の差は歴然です。コマンドの素晴らしさが分かったところで、問題を解いてみましょう!
いくつ正解できる?今日から使えるおすすめコマンド3選
3つの問題
問題は3問出題します。解答は複数あると思いますが、おすすめコマンドなら1行で解答できます。シチュエーションは開発をしていて実際に遭遇しそうな場面を考えてみました。擬似的にコマンドを試す環境を用意しますので、手を動かしてみてください。
* 問題の実行環境は、OS: Max、シェル: zshとなっています。OS: Linux、シェル: bashでも動作確認は取れていますが標準出力が少し異なります。
準備:シェルを開いて以下のコマンドを実行します。
# testディレクトリを作ります。 $ mkdir test $ cd test # それぞれ下記の中身となるように、ファイルに指定文字列を書き込みます。 # わからない方はワンライナーで実行するおまじないと思ってください。それぞれ自分の手で作っても大丈夫です。 $ for j in {1..3}; do for i in {1..3}; do echo $i 'Hello World!' ;done >test_$j.txt ;done $ for j in {4..6}; do for i in {4..6}; do echo $i Bye! ;done > test_$j.txt ;done $ ls test_1.txt test_2.txt test_3.txt test_4.txt test_5.txt test_6.txt # test_1.txtの中身を確認してみます.test_2.txt、 test_3.txtも中身は同じです。 $ cat test_1.txt 1 Hello World! 2 Hello World! 3 Hello World! # test_4.txtの中身を確認してみます。test_5.txt、 test_6.txtも中身は同じです。 $ cat test_4.txt 4 Bye! 5 Bye! 6 Bye!
【問題1】自分が今いるディレクトリの下にあるファイルの中から”Hello”という文字が存在するファイルを教えてください
自分が初めて見るアプリのソースコードを読み進めて理解しようとしています。コードは複数のファイルにまたがっており、なんの変数があるか探さなくてはなりません。
【問題2】編集前test_1.txtと編集後test_4.txtを比べて違う箇所を見つけてください
先輩に見本コードをもらい、自分で一部編集して新しいタスク仕様に修正することになりました。しかし、修正したコードは正しく動かず、先輩のコードと何が違うのかを考えなくてはなりません。
【問題3】消去したいファイル名リストにあるファイルを削除してください
データ解析で大量のファイルを作成しました。作成したファイルの中で中身を間違って作ってしまったものが存在するため消去することになりました。
消去したいファイル名リスト:
test_2.txt test_3.txt test_5.txt test_6.txt
正解例、解説、便利ポイント
おすすめしたいコマンドはgrep、 diff、 xargsの3つです。
問題は複数の解答例が存在すると思いますが、1行で解答できるものを紹介します!
【問題1】grep ファイルの検索
問題「自分が今いるディレクトリの下にあるファイルの中から”Hello”という文字が存在するファイルを教えてください」
正解例$ grep -rl "Hello" ./ .//test_2.txt .//test_3.txt .//test_1.txt
解説
全てのファイルを開いてエディタの検索機能を使うという解答は時間がかかりすぎるため不正解です。
正解例のコマンドは、カレントディレクトリ(./)以下にあるファイルから”Hello”を含むファイルを再帰的に検索します。grepコマンドはファイルの中で文字列やパターンが含まれている行を検索するときに使います。
-rは、ディレクトリを指定した場合にサブディレクトリ内のファイルも含めて検索します。
-lは一致するものが含まれているファイルのファイル名を表示します。
一般化すると以下のように表すことができます。
grep <option> "検索したい文字列" <ディレクトリorファイル名>
* 似たコマンドにfindがあります。grepがファイルの中身が検索対象ですが、findはファイル名が検索対象となります。
便利ポイントgrepはファイル、ディレクトリの中身の文字列一致検索ができるコマンドです。私はファイル名を指定するなら、エディタで開いて検索すればいいと思っていました。
しかし、ディレクトリを指定することで複数のファイルの中身を一度に検索できる点がとても便利です。検索する言葉も一意の文字列以外にも正規表現を用いて汎用的な検索をすることもできます。私は初めて見るソースコードを理解するときにかなり助かりました。
【問題2】diff ファイルの差分
問題「編集前test_1.txtと編集後test_4.txtを比べて違う箇所を見つけてください。」
正解例$ diff -u test_1.txt test_4.txt --- test_1.txt 2021-10-21 13:19:30.000000000 +0900 +++ test_4.txt 2021-10-21 13:19:35.000000000 +0900 @@ -1,3 +1,3 @@ # “-“が1-3行目、”+”は1-3行目が対象という意味 -1 Hello World! # -がtest_4.txtでなくなった行 -2 Hello World! -3 Hello World! +4 Bye! # +がtest_4.txtで増えた行 +5 Bye! +6 Bye!
解説
ファイルをそれぞれcat、 lessしたりエディタで開いて目で比べるのは大変です。
diffコマンドは指定したファイル同士の差分を表示してくれます。オプションによって検索の仕方や差分の表示の仕方が色々あります。-rをつけることでディレクトリ同士の差分も表示できます。私は-u オプションをつけて表示することが多いです。
一般化すると以下のように表すことができます。
diff <option> fromfile tofile
便利ポイント
何かファイルに変更があったのはわかるが、その箇所がわからない時はdiffコマンドの出番です。ファイル同士の差分を取ることができるので、違う部分がすぐわかります。
特にスペースや改行コードなど目で見てもわかりづらい差がわかる点が便利です。
私は開発する際gitというバージョン管理ツールを用いてコードを管理しているのですが、git diffはよく使います。コミットする(簡単にいうと最新の変更をgitに保存する)前にどんな変更があったか必ずチェックすることでミスを減らすようにしています。
【問題3】xargs 標準入力からコマンドラインを作成して実行
問題「消去したいファイル名リストにあるファイルを削除してください。」
正解例# 例1 $ ls ./ | grep -v -e 'test_1.txt' -e 'test_4.txt' | xargs rm # 例2 $ find -mindepth 1 -not -name "test_1.txt" -not -name "test_4.txt" | xargs rm # 例3 #ファイルリストをlist.txtに書き込んで以下を実行 $ cat list.txt | xargs rm
解説
rmコマンドをファイル数分くりかえした方はとても疲れたのではないでしょうか。
xargsコマンドは
コマンド1 | xargs コマンド2
とすることでコマンド1で実行して標準出力された結果をコマンド2の引数として渡してあげることができます。
例1、 2では、”test_1.txt”、 “test_4.txt”以外のファイルをgrepまたはfindコマンドで検索し、その結果をrmコマンドに渡しています。今回は対象ファイルが少ないので、ベタ書きできますが、ファイル数が多い場合は、例3のようにする方がいいかもしれません。
例3では、catコマンドでlist.txtの中身を標準出力し、その結果をrmコマンドに渡すことで、ファイルを削除します。
*|パイプは2つ以上のコマンドをつなげる役目をしています。
* grep -v やfind -not は一致したものを除外するオプションです。
* find -mindepth 1 はカレントディレクトリ(mindepth=0)を対象外にするためです。
* xargsコマンドはMac(FreeBSD版)とLinux(GNU版)で動作が微妙に異なります[1]。今回の例では問題ないと思います。
普通ならコマンドに渡す因数が多くなると書くのは大変です。しかし、xargsコマンドを使うことで、一方のコマンドの結果を利用して、もう一方のコマンドの引数を省略できます。使い方次第で、強力な武器になるでしょう。
他にも、私はファイルの中の文字列を一気に置換したいときに使うことがあります。例えば、開発しているWEBアプリの変数や、関数名を変更したとします。そのネームは他の複数のファイルでインポートしており、全てのファイルに変更を反映させなければなりません。そんなときに活躍するのが以下のコマンドです。
grep -rl 'Hello' ./* | xargs sed -i.bak "s/Hello/Goodbye/g"
関係するファイルをgrepで探し、対象の文字列をHello→Goodbyeに置換します。
sedコマンドは文字列を置換するときに使えるコマンドですが、環境によって動作が異なるようなので気をつけてください[2]。-iはファイルを直接編集するコマンドですが、-i.bakとすることでバックアップファイルを作成してくれます。
またsedコマンドは元に戻せないので、間違って置換してしまうと元に戻すのは困難です。そのためバックアップファイルを作成しておくか、gitなどのバージョン管理ツールで変更前に戻せるようにしておくと安心でしょう。
参考サイト:
[1]
LinuxのコマンドはMacOSXでそのまま動くとは限らない
[2]
MacとLinuxでは、sedの動作が異なるので注意 | ITを使っていこう
まとめ
知らないコマンドはありましたでしょうか?
このコマンドを知っていると人間の作業が大幅に短縮できる可能性があるものをピックアップしてみました。
今回紹介したコマンドはほんの一部でしたが、オプションを変えるだけでも、違った場面で力を発揮してくれるでしょう。これを機に、今まで知らなかったコマンドを新たに覚えてみてはいかがでしょうか。