ref. https://qiita.com/ko1nksm/items/9650ed1fc21d668f2732?utm_source=pocket_mylist
$ [プリフィックス]... コマンド名 [サフィックス]...
※ 以下の例はenv
コマンドを省略しているが、すべての環境で省略できるわけではありません(MacのZshやBashでは省略できます)。
$ date 2021年 11月 8日 月曜日 20時00分26秒 JST
$ LANG=C date Mon Nov 8 20:01:54 JST 2021
$ date 2021年 11月 8日 月曜日 20時03分17秒 JST
https://qiita.com/ko1nksm/items/9650ed1fc21d668f2732?utm_source=pocket_mylist
LANG=C date # 一時的な変数代入 # 厳密にはシェル関数の場合は・・・と長い話があるのですが省略します LANG=C # 恒久的な変数代入
https://qiita.com/ko1nksm/items/9650ed1fc21d668f2732?utm_source=pocket_mylist
※ Linuxのローカライゼーション系LANG変数:langについて
linuxを参照。
同一シェルで複数のプロセスが作成される例を以下に示す。
※サブシェルが作成されるわけではない。
# sample.sh
echo "process"
# グルーピング{}はカレントシェルで実行
# グルーピング()はサブシェルで実行
{
while : ;do
echo "child processs"
done
}
上記のスクリプトを実行すると 親プロセスと子プロセスの2つのプロセスが作成される。
$ ps auxf | grep bash
ec2-user 13165 0.0 0.4 124992 4188 pts/1 Ss 05:25 0:00 \_ -bash
ec2-user 13227 22.7 0.1 124992 1080 pts/1 S+ 05:35 0:05 \_ -bash
(プロセスとは関係なく)以下の処理でサブシェルが作成される。
サブシェルは以下のような特徴を持つ。
入門UNIXシェルプログラミング(p26)
|
:サブシェルで実行$ sh script.sh
:サブシェルで実行$ ./script.sh
:サブシェルで実行(実行権限付与済み $ chmod u+x script.sh
)$ . ./script.sh
:カレントシェルで実行$ source script.sh
:カレントシェルで実行(.
コマンドと異なり相対パスまたは絶対パスで指定する必要がない)exec
コマンド: $ exec {{command}}
このようにしてコマンドラインからシェルスクリプトを起動すると、 カレントシェルは子プロセスとして もう一つシェルを走らせ、そこでシェルスクリプトを実行します。 この実際にスクリプトを実行するために走るシェルを サブシェル といいます。 子プロセスのサブシェルは親プロセス(カレントシェル)の環境を受け継ぐこと はできますが、その逆はできません。例えば、実行属性を与えたシェルスクリプト を使って環境変数を再設定しようとしても、再設定されるのはサブシェル側の環境変数 であってカレントシェルのものではありません。
. ./script.sh
:別プロセスを作成せずにカレントシェルのプロセスでスクリプトが実行されるため、スクリプト実行後にカレントシェルでscript.shで定義された変数を使用できる。別プロセスでスクリプトが実行されるため、スクリプト実行後にカレントシェルでsample.shで定義された変数を使用できない。
# script.sh
HELLO=hello
echo $HELLO
$ sh ./script.sh
hello
$ echo $HELLO
// 何も表示されない
()
によるグルーピングはサブシェルで実行{}
によるグルーピングはカレントディレクトリで実行echoやprintfのように、同じ名前で実行ファイルで存在しているコマンド(ex:/bin/echo)と、シェルの組み込みとして存在しているコマンドがあったりする。 シェルスクリプト上ではパスを指定しないと組み込みのものが使われる。機能に差異があったりするので、実行ファイルのほうを使う場合は明示的にパスを指定するなどして区別する。
シェルのワイルドカードと正規表現やプログラム言語固有のワイルドカードの違いに注意する。
*
:任意の0以上の文字列(0文字以上でも良いことに注意)?
:任意の1文字''
):文字列を表す(変数を展開しない)""
):文字列を表す(変数を展開する)$(command)
もcommandを実行するが後述するように$(command)
はネストができる文字 | 内容 |
---|---|
' | すべてキャラクタがエスケープされます。 |
" | $で変数を展開します。$, `,\, "はエスケープする必要があります。 |
クォートなし | 要調査 |
$ nowTime=2021-01-01
$ echo '時刻:${nowTime}'
// 時刻:${nowTime}
$ echo "時刻:${nowTime}"
// 時刻:2021-01-01
$ echo "時刻:`date`"
// 時刻:Sat 23 Oct 2021 12:38:37 PM UTC
$ echo "時刻:"$(date)
// 時刻:Sat 23 Oct 2021 12:38:37 PM UTC
echo Hello World
// Hello World # クォートで囲まなくても表示
echo 'Hello' World
// Hello World # 文字列の連結に演算子は必要ない
MY_NAME='Hiroshi Sawai'
echo MY_NAME
// Hiroshi Sawai
My_NAME=Hiroshi Sawai
echo MY_NAME
// bash: Sawai: command not found
echo ''
// なにも表示されない
echo
// シングルクォート内のシングルクォートをエスケープする方法はない
// エスケープできない
echo '\''
>
// 'は表示できない
// 以下のようにシングルクォートの外ではエスケープで表示できる
$ echo \'foo\'
// foo
$(command)
はバッククォートと同じようにcommandを実行する。
ただしバッククォートより高機能でネストして使用できる。
$ echo $(date -d @$(date +%s))
// date +%s はUnixタイムスタンプを出力
// Sat 23 Oct 2021 12:49:17 PM UTC
`{{comand}}`か$({{command}})
でコマンド実行結果を変数に代入。
# 引用元:https://qiita.com/Ping/items/57fd75465dfada76e633
TODAY=`date +'%Y/%m/%d'`
echo $TODAY
NOWTIME=$(date +'%H:%M:%S')
echo $NOWTIME
$ npm install 2> npm_warning.log
ポイントをまとめると以下のとおりとなる。
- = を使う
- 値の設定時は変数名の先頭に $ を付けない ($ は参照時のみ)
- = の前後にスペースを入れない (前後にスペースがあるとエラー)
- 型は存在しない (declare コマンドや typeset コマンドで似たようなことができるが推奨はしない)
- 変数名の大文字・小文字は区別される (VAR と var は別物)
特に「2」は初心者が犯しがちなミスなので注意すること。
変数を使用する | UNIX & Linux コマンド・シェルスクリプト リファレンス
$0 # シェルスクリプト名
$1~$9 # 1番目~9番目の引数
$* # すべての引数(詳細後述)
$@ # すべての引数(詳細後述)
$# # 引数の数
$? # 直前に実行したコマンドの終了ステータス。0は成功、0以外は失敗
$- # シェルの実行オプション (/bin/bash -opt)
$$ # シェルのプロセスID
$! # 最後に実行したバックグランドプロセスのプロセスID
$_ # 最後に実行したコマンドの最後の引数
引用元:https://www.tohoho-web.com/ex/shell.html#special
変数PATH
の値を確認します。
$ echo ${PATH}
パスを通すとは、シェル設定ファイル(.bash_profile
や.zshrc
で、環境変数PATH
にパスを追加することです。
export
で環境変数(この場合はPATH
)を更新します。
PATH=$PATH:/path/to/add
export PATH
(1) PATH
の優先順位を確認
$ cat /etc/paths
// 優先度の高い順に表示
例えば以下のように、.bash_profile
で優先順位を変更できます。
PATH=/path/to/dir:$PATH
export PATH
(2) sourceコ
マンド
.bash_profile
を変更したときは、ログインし直さないと変更が反映されません。source
コマンドを使うとログインし直さなくても変更が反映されます。.
コマンドはsource
コマンドとほぼ等価です.
$ source /path/to/.bash_profile
// or
$ . /path/to/.bash_profile
本当に正しい .bashrc と .bash_profile の使ひ分け - Qiita
export
を使用する#!/bin/bash
# script.sh
# このスクリプトはシェル変数が子プロセスでは使用できないことを確認します。
# 実行前にシェルからBAR=BAZとシェル変数を定義してください。
# 次に sh script.sh で子プロセスとして実行してください。
echo '子プロセス'
echo $BAR
$ BAR=BAZ
$ sh script.sh # 子プロセスで実行
子プロセス
<-- $BARは表示されない
# 以下では環境変数として設定されない実装がある(Macのzshでは環境変数として設定される)
$ FOO=BAR
$ export FOO
$ env | grep FOO
// 空
# 以下で環境変数として設定される
$ export FOO=BAR
$ env | grep FOO
// FOO=BAR
# 以下で同様に環境変数として設定される
$ FOO=BAR export FOO
$ env | grep FOO
// FOO=BAR
環境変数の削除。
unset FOO
printenv
コマンド環境変数を表示する。
$ printenv
// 環境変数一覧を表示
$ printenv SHELL
/bin/bash
env
コマンド
$ env
// 環境変数一覧を表示(printenvとほぼ同等)
envは本来は一時的に環境変数を設定してコマンドを実行するために使用される。
// date
// 2022年 1月22日 土曜日 10時25分27秒 JST <--- 変更前
$ env LANG=c date
Sat Jan 22 10:25:55 JST 2022 <---- 一時的に変更
// 一時的に環境変数を設定するのでコマンド実行ごはもとに戻る
// $ date
// 2022年 1月22日 土曜日 10時26分06秒 JST <--- もとに戻る
ZshやBashではenv
は省略可能だが独自使用。
# これでも大丈夫
$ LANG=c date
Sat Jan 22 10:25:55 JST 2022
シェル変数はset
コマンドで一覧表示する。
$ set
// すべてのシェル変数を表示
$ Foo="Bar"
// シェル変数定義
$ set | grep Foo
// Foo=Bar
$ printenv | grep Foo
// 結果なし
$ export Foo
$ printenv | grep Foo # 環境変数になる
// Bar
ref.
https://qiita.com/chihiro/items/bb687903ee284766e879
DB="mysql";
if [[ $DB == "mysql" ]]; then
mysql -u root myapp_test < ${TRAVIS_BUILD_DIR}/bin/infotownlinkwp.sql;
fi
if [[ $DB == "pgsql" ]]; then
psql myapp_test < ${TRAVIS_BUILD_DIR}/bin/infotownlinkwp.sql;
fi
[ ... ]はtestの糖衣構文。...の前後に半角スペースが必要。
[[ ... ]]はbash専用の言語構造で[ ]より高機能。
[ ... ] で使用できる表記。
( exp ) # exp をグルーピング
! exp # exp が偽であれば
exp1 -a exp2 # exp1 かつ exp2 であれば
exp2 -o exp2 # exp1 または exp2 であれば
str1 = str2 # 文字列 str1 と str2 が等しければ
str1 != str2 # 文字列 str1 と str2 が等しくなければ>
-z str # 文字列 str が0文字であれば(zero)
-n str # 文字列 str が0文字で以上であれば(not zero)
str # 文字列 str が0文字で以上であれば(-n str と同じ)
num1 -eq num2 # 数値 num1 が num2 と等しければ(equal)
num1 -ne num2 # 数値 num1 が num2 異なっていれば(not equal)
num1 -ge num2 # 数値 num1 が num2 以上であれば(grater than or equal)
num1 -gt num2 # 数値 num1 が num2 より大きければ(grater than)
num1 -le num2 # 数値 num1 が num2 以下であれば(less than or equal)
num1 -lt num2 # 数値 num1 が num2 より小さければ(less than)
file1 -ef file2 # ファイル file1 が file2 と同一実体であれば(equal file)
file1 -nt file2 # ファイル file1 が file2 より新しければ(newer than)
file1 -ot file2 # ファイル file1 が file2 より古ければ(older than)
-e file # ファイル file が存在していれば
-s file # ファイル file が0バイト以上であれば
-f file # ファイル file がレギュラーファイルであれば
-r file # ファイル file が読み込み可能であれば
-w file # ファイル file が書き込み可能であれば
-x file # ファイル file が実行可能(ディレクトリの場合は移動可能)であれば
-d file # ファイル file がディレクトリであれば
-h file # ファイル file がシンボリックリンクファイルであれば(-Lと同義)
-L file # ファイル file がシンボリックリンクファイルであれば(-hと同義)
-b file # ファイル file がブロックデバイスファイルであれば
-c file # ファイル file がキャラクタデバイスファイルであれば
-p file # ファイル file が名前付きパイプであれば
-S file # ファイル file がソケットファイルであれば
-k file # ファイル file にスティッキービットが設定されていれば(chown o+t)
-u file # ファイル file にセットユーザIDビットが設定されていれば(chown u+s)
-g file # ファイル file にセットグループIDビットが設定されていれば(chown g+s)
-O file # ファイル file が実効ユーザIDに所有されていれば
-G file # ファイル file が実効グループIDに所有されていれば
-t fd # ファイルディスクリプタ fd がターミナルとして開かれていれば
引用元:https://www.tohoho-web.com/ex/shell.html#if-statemant
#!/bin/bash
total=0
for x in 100 200 300
do
total=$(expr $total + $(expr $x \* 2))
done
echo $total
#!/bin/bash
total=0
for x in 100 200 300
do
total=`expr $total + \`expr $x \* 2\``
done
echo $total
// input.txt
abc
def
ghi
while read LINE
do
echo $LINE
done < input.txt
https://qiita.com/youcune/items/fcfb4ad3d7c1edf9dc96
ディレクトリのファイル一覧を取得
#!/bin/bash
for f in `find . -maxdepth 1 -type f`
do
echo $f
done
ディレクトリ内のファイルサイズを取得
#!/bin/bash
for f in `find . -maxdepth 1 -type f`
do
wc -c < $f
done
ディレクトリサイズ表示
#!/bin/bash
for d in `find . -maxdepth 1 -type d`
do
du $d
done
文字列結合
#!/bin/bash
lines=''
while read line
do
lines=$lines$line
done < file.txt
echo $lines
file.txt
aaa
bbb
ccc
実行
$ ./script.sh
aaabbbccc
expr
#!/bin/bash
total=0
for x in 100 200 300
do
total=`expr $total + \`expr $x \* 2\``
done
echo $total