シェルスクリプト
bashで変数を割り当てるには、foo=bar
構文を使用$foo
し、アクセス変数の値を使用します。注foo = bar
それはパラメータ= fooとbarで呼び出されたプログラムとして解釈されているため、仕事をしません。一般的に、シェルスクリプトでは、スペース文字によって実行パラメータが分割され、最初は混乱する可能性があるため、常にこのオプションをオンにしてください。
文字列は、bashのことができます'
し、“
セパレータを定義しますが、彼らは同じではありません。'
区切られた文字列は、しかしで、テキスト文字列変数の値が交換されていないで“
区切られた文字列。
foo=bar
echo "$foo"
# prints bar
echo '$foo'
# prints $foo
ほとんどのプログラミング言語と同様に、bashの支持体は制御技術を流し含め、if
、case
、while
とfor
。同様に、bashにはパラメーターを受け入れ、それらを操作できる関数があります。以下は、ディレクトリを作成してそこにcdする関数の例です。
mcd () {
mkdir -p "$1"
cd "$1"
}
ここでは$1
最初の引数のスクリプト/関数です。他のスクリプト言語とは異なり、bashはさまざまな特殊変数を使用して、パラメーター、エラーコード、およびその他の関連変数を参照します。
$0
-スクリプトの名前
$1
$9
-スクリプトのパラメータ。$ 1は最初のパラメーターなどです。
$@
-すべてのパラメーター
$#
-パラメーターの数
$?
-前のコマンドの戻りコード
$$
-現在のスクリプトのプロセス識別番号
!!
-最後のコマンド全体(パラメーターを含む)。一般的なパターンは、権限がないために失敗したコマンドを1つだけsudo!!
実行し、sudoを使用してすばやく実行できます
$_
-最後のコマンドの最後のパラメーター。対話型シェルを使用している場合は、Esc
と入力してフォローする.
ことで、この値をすばやく取得することもできます。
コマンドは通常STDOUT
により、出力を返すSTDERR
リターンエラー、スクリプトがエラーを報告し、より親しみやすい方法で、エラー戻りコード。リターンコードまたは終了ステータスは、スクリプト/コマンドが実行方法を伝達する方法です。値0は通常すべてが正常であることを示し、0以外の値はエラーが発生したことを示します。
終了コードは、&&
(および演算子)および||
(または演算子)を使用してコマンドを条件付きで実行するために使用できます。コマンドはセミコロンで;
同じ行に区切ることもできます。true
プログラムの戻りコードは常に0で、false
コマンドの戻りコードは常に1です。いくつかの例を見てみましょう
false || echo "Oops, fail"
# Oops, fail
true || echo "Will not be printed"
#
true && echo "Things went well"
# Things went well
false && echo "Will not be printed"
#
false ; echo "This will always run"
# This will always run
別の一般的なパターンは、コマンドの出力を変数として期待することです。これは、コマンド置換によって実行できます。配置するたびに$(CMD)
実行されCMD
、コマンドの出力を取得して、置き換えます。たとえば、$(ls)
この操作をファイルで実行すると、シェルが最初ls
に呼び出され、次にこれらの値で反復されます。あまり知られていない同様の機能がプロセス置換です。<(CMD)
これは、CMDを実行し、出力を一時ファイルに入れて、ファイルの名前に置き換えます<()
。これは、コマンドの期待値がSTDINではなくファイルで渡される場合に役立ちます。例えば、diff<(ls foo)<(ls bar)
ディスプレイfoo
とbar
ファイルの違い。
これは大量の情報のダンプであるため、これらの特性を示す例を見てみましょう。私たちは、引数、文字列でそれを提供foobar
するgrep
ことを見つけられない場合は、それをコメントとしてファイルに追加され、。
#!/bin/bash
echo "Starting program at $(date)" # Date will be substituted
echo "Running program $0 with $# arguments with pid $$"
for file in $@; do
grep foobar $file > /dev/null 2> /dev/null
# When pattern is not found, grep has exit status 1
# We redirect STDOUT and STDERR to a null register since we do not care about them
if [[ $? -ne 0 ]]; then
echo "File $file does not have any foobar, adding one"
echo "# foobar" >> "$file"
fi
done
比較では$?
、0でないかどうかをテストしました。Bashはこのような比較を数多く実装しています。Bashで比較を実行する場合、詳細なリストはmanページにあります。[[]]
単純な角かっこの代わりに二重角かっこを使用してみてください[]
。
スクリプトを開始するときは、通常、同様のパラメーターを指定する必要があります。Bashは、ファイル名の展開と式の展開を行うことで、このプロセスを簡略化できます。これらのテクニックは、一般にシェルボールと呼ばれます。
ワイルドカード-ある種のワイルドカード照合を実行する場合は常に、それぞれ1つまたは任意の数の文字を使用?
して*
照合できます。たとえば、ファイル与えられfoo
、foo1
、foo2
、foo10
とbar
、コマンドがrm foo?
削除されますfoo1
とfoo2
しながら、rm foo*
さらには削除bar
すべてのコンテンツの外を。
サスペンダー{}
-限り、一連のコマンドで共通部分があるので、あなたは中括弧が自動的にそれを拡張するためのbashを使用することができます。これは、ファイルを移動または変換するときに非常に便利です。
convert image.{png,jpg}
# Will expand to
convert image.png image.jpg
cp /path/to/project/{foo,bar,baz}.sh /newpath
# Will expand to
cp /path/to/project/foo.sh /path/to/project/bar.sh /path/to/project/baz.sh /newpath
# Globbing techniques can also be combined
mv *{.py,.sh} folder
# Will move all *.py and *.sh files
mkdir foo bar
# This creates files foo/a, foo/b, ... foo/j, bar/a, bar/b, ... bar/j
touch {foo,bar}/{a..j}
touch foo/x bar/y
# Show differences between files in foo and bar
diff <(ls foo) <(ls bar)
# Outputs
# < x
# ---
# > y
端末から呼び出すためにbashでスクリプトを書く必要がないことに注意してください。たとえば、パラメータを逆順に出力する単純なPythonスクリプトは次のとおりです
#!/usr/local/bin/python
import sys
for arg in reversed(sys.argv[1:]):
print(arg)
スクリプトの先頭にシバン行を含めたため、シェルはシェルコマンドの代わりにpythonインタープリターを使用してこのスクリプトを実行することを認識しています。使用env
シェバング行は良い習慣です書くためのコマンドを、コマンドは、コマンドは、スクリプトの移植性を向上させることで、システム内の任意の場所に解決されます。ロケーションの問題を解決するためenv
に、最初のレッスンで紹介したPATH
環境変数を使用します。この例では、シバン線はのようになり#!/usr/bin/env python
ます。
シェル関数とスクリプトのいくつかの違いを覚えておく必要があります。
-
関数はシェルと同じ言語を使用する必要があり、スクリプトは任意の言語で記述できます。これが、スクリプトを含むシバンが重要である理由です。
-
関数は、その定義を読み取るときに一度読み込まれます。スクリプトが実行されるたびにロードされます。これにより、関数の読み込みが少し速くなりますが、関数を変更するたびに、その定義を再読み込みする必要があります。
-
関数は現在のシェル環境で実行され、スクリプトは独自のプロセスで実行されます。したがって、関数は現在のディレクトリの変更など、環境変数を変更できますが、スクリプトはできません。スクリプトは、exportを使用してエクスポートされた値の環境変数を渡します
-
他のプログラミング言語と同様に、関数はモジュール化、コードの再利用、シェルコードの明確化のための強力な構成要素です。通常、シェルスクリプトには独自の関数定義が含まれます。
シェルツール
コマンドの使用方法を確認する
この時点で、エイリアスセクション(やls -l
、mv -i
などmkdir -p
)でコマンドのフラグを見つける方法を知りたい場合があります。より一般的には、コマンドが与えられたときに、それが何をするか、そのさまざまなオプションをどのようにして見つけるのですか?
シェルコースで見たように、最初の方法は、-h
or --help
フラグを使用してコマンドを呼び出すことです。より詳細な方法は、man
コマンドを使用することです。man
指定したコマンドのマニュアルページ(マンページと呼ばれる)を提供する、manualの省略形です。たとえば、前に示したフラグを含め、コマンドの動作とコマンドが使用man rm
するrm
フラグが出力され-i
ます。非ネイティブコマンドをインストールした場合でも、開発者がマンページエントリを記述し、それをインストールプロセスの一部として含めると、マンページエントリも含まれます。対話型ツール(ncursesベースのツールなど)では、通常、:help
コマンドを使用するか、プログラムに入力します?
。
マンページがコマンドの詳細な説明である場合があり、一般的な使用例で使用される記号/構文を解読するのは困難です。TLDRページは優れた補足ソリューションであり、使用するオプションをすばやく見つけることができるようにコマンドを提供する使用例に焦点を当てています。
ファイルを探す
すべてのプログラマが直面する最も一般的な反復的なタスクの1つは、ファイルまたはディレクトリを見つけることです。すべてのUNIXライクなシステムfind
に付属しています。これは、ファイルを見つけるための優れたシェルツールです。find
特定の条件を満たすファイルは再帰的に検索されます。いくつかの例:
# Find all directories named src
find . -name src -type d
# Find all python files that have a folder named test in their path
find . -path '**/test/**/*.py' -type f
# Find all files modified in the last day
find . -mtime -1
# Find all zip files with size in range 500k to 10M
find . -size +500k -size -10M -name '*.tar.gz'
ファイルの一覧表示に加えてfind
、クエリに一致するファイルに対して操作を実行することもできます。このプロパティは、単調になる可能性のあるタスクを簡略化するのに非常に役立ちます。
# Delete all files with .tmp extension
find . -name '*.tmp' -exec rm {} \;
# Find all PNG files and convert them to JPG
find . -name '*.png' -exec convert {} {.}.jpg \;
けれどもfind
、どこでも、それは構文を覚えておくことが難しい場合があります。たとえば、単純にパターンに一致するファイルを見つけるには、ファイルを実行する必要がありますfind -name '*PATTERN*'
(パターンマッチングで大文字と小文字を区別しない場合は、実行します-iname
)。これらのシーンのエイリアスの作成を開始できますが、シェルの哲学の一部として、別の方法を使用して探索することをお勧めします。シェルの最も優れた機能の1つは、プログラムを呼び出すだけで特定のプログラムの代替を見つける(または独自のプログラムを作成する)ことができることです。たとえばfd
、シンプルで高速かつユーザーフレンドリーな検索方法です。これは、カラー出力、デフォルトの正規表現マッチング、Unicodeサポートなど、いくつかの優れたデフォルト設定を提供し、私にはより直感的な構文のように思えます。検索PATTERN
モードの構文はfd PATTERN
です。
ほとんどの人が同意するfind
とfd
非常に優れているが、一部の人は知っているしたい場合がありますたびに、そのファイルの検索効率はなく、クイック検索のためのいくつかのインデックスまたはデータベースをコンパイル。これがlocate
目的です。更新されたデータベースをlocate
使用しupdatedb
ます。ほとんどのシステムでupdatedb
は、cron
毎日更新されます。したがって、2つの間のトレードオフは、速度と鮮度です。さらに、find
同様のツールでは、ファイルサイズ、変更時間、ファイルのアクセス許可などの属性をlocate
使用してファイルを検索し、名前のみを使用することもできます。
コードを探す
ファイルを見つけることは便利ですが、通常はファイルの内容を見つけることです。一般的なシナリオは、特定のパターンを含むすべてのファイルと、これらのファイル内のパターンの場所を検索することです。これを実現するために、ほとんどのUNIXライクなシステムは、grep
入力テキストからパターンを照合するための汎用ツールを提供しています。
grep
それを非常に用途の広いツールにする多くの兆候があります。私はよく一致する行の前後のコンテキストを取得するために使用-C
し、一致-v
を逆にするために使用します。つまり、パターンに一致しないすべての行を印刷します。たとえばgrep -C 5
、試合の前後に5行が印刷されます。多くのファイルをすばやく解析-R
することになると、再帰的にディレクトリに入り、文字列に一致するテキストファイルを見つけるため、それを使用する必要があります。
ただしgrep -R
、.git
フォルダーを無視する、マルチCPUサポートを使用するなど、さまざまな方法で改善できます。したがって、ack、ag、およびrgを含む、開発された代替手段の不足はありません。彼らは素晴らしいですが、基本的に同じニーズを満たします。ripgrep
(rg
)の使用は、その速度と直感性を考慮して主張します。いくつかの例:
# Find all python files where I used the requests library
rg -t py 'import requests'
# Find all files (including hidden files) without a shebang line
rg -u --files-without-match "^#!"
# Find all matches of foo and print the following 5 lines
rg foo -A 5
# Print statistics of matches (# of matched lines and files )
rg --stats PATTERN
find
/ と同様にfd
、これらのツールのいずれかを使用してこれらの問題をすばやく解決できることを知っておくことが重要ですが、使用する特定のツールはそれほど重要ではありません。
シェルコマンドを見つける
これまでのところ、ファイルとコードを見つける方法を学習しましたが、シェルでより多くの時間を費やすようになると、ある時点で入力した特定のコマンドを見つけたい場合があります。最初に知っておくべきことは、上矢印が前のコマンドに戻ることです。それを押し続けると、シェルの履歴をゆっくりと参照します。
history
このコマンドを使用すると、プログラムからシェルの履歴にアクセスできます。シェルの履歴を標準出力に出力します。そこで検索したい場合は、出力パイプラインをに送信しgrep
てパターンを検索できます。history | grep find
サブストリング「find
」を含むコマンドが出力されます。
ほとんどのシェルでは、を使用Ctrl+R
して、履歴の後方検索を実行できます。を押した後Ctrl+R
、部分文字列を入力して、履歴のコマンドと一致させることができます。押し続けると、履歴入力が循環します。これは、zshの上矢印/下矢印で有効にすることもできます。またCtrl+R
、素敵な追加があり、それが結合fzf使用することです。fzfは、多くのコマンドで使用できる汎用のファジーファインダーです。
歴史に基づいた自己手がかりhistory-based autosuggestions
。この機能は、fishシェルによって最初に導入されました。入力した最新のコマンドを使用して、現在のシェルコマンドを自動的に動的に完了します。このコマンドは、現在のシェルコマンドと共通のプレフィックスを共有します。
最後に、先頭のスペースでコマンドを開始すると、シェルの履歴に追加されないことを覚えておいてください。これは、パスワードやその他の機密情報を使用してコマンドを入力する場合に非常に役立ちます。先頭のスペースを追加しないことを間違えた場合は、.bashúhistory
またはを編集して.zhistory
、エントリを手動で削除できます。
ディレクトリナビゲーション
これまで、これらの操作を実行する必要がある場所にいると想定していましたが、ディレクトリをすばやくナビゲートするにはどうすればよいですか?これを行うには、シェルエイリアスの作成やln-sを使用したシンボリックリンクの作成など、多くの簡単な方法がありますが、開発者は今、非常に巧妙で複雑なソリューションを見つけています。
このコースの主題と同様に、通常は一般的な状況に合わせて最適化する必要があります。頻繁に、または最近使用されたファイルやディレクトリを見つけることは、fasd fasdなどのツールによって頻度(つまり、頻度と最近の使用頻度)でソートできます。最も直接的な使用法はautojumpです。これは、frecentディレクトリのサブストリングを使用してすばやくcdできるzコマンドを追加します。E. g。/ home / user / files / cool_projectに頻繁にアクセスする場合は、そこにジャンプするだけです。
ディレクトリ構造ツリー、BROOT、または成熟したファイルマネージャー(NNNやRanger-Reverなど)の概要をすばやく取得するためのより洗練されたツールが存在します。