https://betterdev.blog/minimal-safe-bash-script-template/
https://qiita.com/blackenedgold/items/c9e60e089974392878c8
function print_info() {
echo -e "\e[1;36m$*\e[m" # cyan
}
function print_notice() {
echo -e "\e[1;35m$*\e[m" # magenta
}
function print_success() {
echo -e "\e[1;32m$*\e[m" # green
}
function print_warning() {
echo -e "\e[1;33m$*\e[m" # yellow
}
function print_error() {
echo -e "\e[1;31m$*\e[m" # red
}
function print_debug() {
echo -e "\e[1;34m$*\e[m" # blue
}
echo -e "$BIRed"$line"$Color_Off"
####################
### Color Define ###
####################
# Reset
Color_Off="\033[0m" # Text Reset
# Regular Colors
Black="\033[0;30m" # Black
Red="\033[0;31m" # Red
Green="\033[0;32m" # Green
Yellow="\033[0;33m" # Yellow
Blue="\033[0;34m" # Blue
Purple="\033[0;35m" # Purple
Cyan="\033[0;36m" # Cyan
White="\033[0;37m" # White
# Bold
BBlack="\033[1;30m" # Black
BRed="\033[1;31m" # Red
BGreen="\033[1;32m" # Green
BYellow="\033[1;33m" # Yellow
BBlue="\033[1;34m" # Blue
BPurple="\033[1;35m" # Purple
BCyan="\033[1;36m" # Cyan
BWhite="\033[1;37m" # White
# Underline
UBlack="\033[4;30m" # Black
URed="\033[4;31m" # Red
UGreen="\033[4;32m" # Green
UYellow="\033[4;33m" # Yellow
UBlue="\033[4;34m" # Blue
UPurple="\033[4;35m" # Purple
UCyan="\033[4;36m" # Cyan
UWhite="\033[4;37m" # White
# Background
On_Black="\033[40m" # Black
On_Red="\033[41m" # Red
On_Green="\033[42m" # Green
On_Yellow="\033[43m" # Yellow
On_Blue="\033[44m" # Blue
On_Purple="\033[45m" # Purple
On_Cyan="\033[46m" # Cyan
On_White="\033[47m" # White
# High Intensty
IBlack="\033[0;90m" # Black
IRed="\033[0;91m" # Red
IGreen="\033[0;92m" # Green
IYellow="\033[0;93m" # Yellow
IBlue="\033[0;94m" # Blue
IPurple="\033[0;95m" # Purple
ICyan="\033[0;96m" # Cyan
IWhite="\033[0;97m" # White
# Bold High Intensty
BIBlack="\033[1;90m" # Black
BIRed="\033[1;91m" # Red
BIGreen="\033[1;92m" # Green
BIYellow="\033[1;93m" # Yellow
BIBlue="\033[1;94m" # Blue
BIPurple="\033[1;95m" # Purple
BICyan="\033[1;96m" # Cyan
BIWhite="\033[1;97m" # White
# Bold High Intensty
BIBlack="\033[1;90m" # Black
BIRed="\033[1;91m" # Red
BIGreen="\033[1;92m" # Green
BIYellow="\033[1;93m" # Yellow
BIBlue="\033[1;94m" # Blue
BIPurple="\033[1;95m" # Purple
BICyan="\033[1;96m" # Cyan
BIWhite="\033[1;97m" # White
# High Intensty backgrounds
On_IBlack="\033[0;100m" # Black
On_IRed="\033[0;101m" # Red
On_IGreen="\033[0;102m" # Green
On_IYellow="\033[0;103m" # Yellow
On_IBlue="\033[0;104m" # Blue
On_IPurple="\033[10;95m" # Purple
On_ICyan="\033[0;106m" # Cyan
On_IWhite="\033[0;107m" # White
[]はtestコマンドのalias
・空白を含む文字列をクォートしなくてもOK(var="abc 123"のとき、 "$var"->$varでいい)
・正規表現が使える
・パターンマッチができる
・ANDやORに&&や||が使える
():配列定義。var=(a b c)
(())は演算に使う。
((var+1))
{}
・変数展開(${var})
・パラメータ展開({a..c}等)に使う
・コマンドをまとめる
{
echo hoge
echo fuga
echo piyo
} > echo.log
{{}}は使用することなさそう
$()は``と同じでコマンド実行
$(())はインライン演算。(())と違ってインラインで使用できる
docllar.sh abc 123と実行
dollar.sh
#!/bin/bash
echo $0
# -> dollar.sh
echo $1
# -> abc
echo "$*"
# -> abc 123
# $@との違いはabc 123を一つの文字列として使用する点
echo "$@"
# -> abc 123
# $*との違いはabc 123を一つずつ使用できる点
# for i in "$@";do
# echo $i
# done
# とかできる。
# 基本的には$*よりこっちを使うこと
echo $#
# -> 2 引数の数
echo $$
# 実行時のプロセスID
echo $!
# 前回実行コマンドの実行結果。
echo $?
# 前回実行コマンドの実行結果。成功は0
echo $-
# スクリプト内で有効になっているフラグを表示
echo $_
# -> /bin/bash 実行シェル取得
!$:前回の引数を取得
less /etc/passwd
vi !$
service httpd restart
sudo !!
標準エラー出力をリダイレクト
ls /home/bin 2> hoge.log
標準出力と標準エラー出力をリダイレクト
ls /home/bin &> hoge.log
ls /home/bin >& hoge.log
ls /home/bin > hoge.log 2>&1
teeで標準出力とファイルを両方に出力
ls /home/bin | tee hoge.log
・出力をファイルに書く
exec &>file とすると以降のコマンド実行結果はすべてfileに書かれる
・任意のファイルディスクリプタを開く
exec 3> file
echo "hoge" >& 3
exec 3>&- # 閉じる
<<-とする
<<<
プロセスの結果を一時ファイルのようにコマンドに渡すことができる機能
diff <(sort file1.txt | uniq) <(sort file2.txt | uniq)
エラーが起きた際に一時ファイルを消して終了したい場合等に使用する
trapコマンドを使う
trap 実行したいコマンド/関数 EXIT
${parameter#word}先頭から最短一致
${parameter##word}先頭から最長一致
${parameter%word}末尾から最短一致
${parameter%%word}末尾から最長一致
e.g.)
echo ${name#*/}
${va/pattern/str} 一つの文字の置
き換え
${va//pattern/str} すべての文字の置き換え
計算
$((TEST_V+1))
切り取り
${var:pos} 位置から末尾まで
${var:pos:len} 位置から長さまで
シェルのオプションを設定する
http://itpro.nikkeibp.co.jp/article/COLUMN/20060227/230881/
set -ue
しておく
-u 未定義の変数を使った場合Stopする
-e エラーがあったらStopする
また、
#!/bin/sh -
とすると、
sh コマンドに、これ以上オプションが無いことを認識させます。
意図しないオプションをセットされることを防ぎます。
local変数を使うときは宣言したあとに使うこと。そうしないと関数の結果を代入したときにおかしくなる
http://deeeet.com/writing/2014/05/18/shell-template/
getopt には重大な落とし穴があります。 それは、スペースや特殊文字が引数に含まれていた場合、正しく処理できないということです。 あるシェルスクリプトで getopt を使った場合、空白や特殊文字は絶対に使うな、という注意書きが必要になります。 これを何とかしのごうとするのは容易ではありません。
なので以下のようなものを自前で書く。しかし、-amのような使い方ができなくなる。特殊だが、2のような感じだとそれも解決できる。
1
PROGNAME = $( basename $0 )
VERSION = "1.0"
usage () {
echo "Usage: $PROGNAME [OPTIONS] FILE"
echo " This script is ~."
echo
echo "Options:"
echo " -h, --help"
echo " --version"
echo " -a, --long-a ARG"
echo " -b, --long-b [ARG]"
echo " -c, --long-c"
echo
exit 1
}
for OPT in "$@"
do
case "$OPT" in
'-h' | '--help' )
usage
exit 1
;;
'--version' )
echo $VERSION
exit 1
;;
'-a' | '--long-a' )
if [ -z "$2" ]] || [[ "$2" = ~ ^-+ ]( -z "$2" ]] || [[ "$2" = ~ ^-+ .md) ; then
echo "$PROGNAME: option requires an argument -- $1" 1> & 2
exit 1
fi
ARG_A = "$2"
shift 2
;;
'-b' | '--long-b' )
if [ -z "$2" ]] || [[ "$2" = ~ ^-+ ]( -z "$2" ]] || [[ "$2" = ~ ^-+ .md) ; then
shift
else
shift 2
fi
;;
'-c' | '--long-c' )
shift 1
;;
'--' | '-' )
shift 1
param+ =( "$@" )
break
;;
-* )
echo "$PROGNAME: illegal option -- '$(echo $1 | sed 's/^-*//')'" 1> & 2
exit 1
;;
* )
if [ ! -z "$1" ]] && [[ ! "$1" = ~ ^-+ ]( ! -z "$1" ]] && [[ ! "$1" = ~ ^-+ .md) ; then
#param=( ${param[@]} "$1" )
param+ =( "$1" )
shift 1
fi
;;
esac
done
if [ -z $param ] ; then
echo "$PROGNAME: too few arguments" 1> & 2
echo "Try '$PROGNAME --help' for more information." 1> & 2
exit 1
fi
2
declare -i argc = 0
declare -a argv =()
while (( $# > 0 ))
do
case "$1" in
-* )
if [ "$1" = ~ 'n' ]( "$1" = ~ 'n' .md) ; then
nflag = '-n'
fi
if [ "$1" = ~ 'l' ]( "$1" = ~ 'l' .md) ; then
lflag = '-l'
fi
if [ "$1" = ~ 'p' ]( "$1" = ~ 'p' .md) ; then
pflag = '-p'
fi
shift
;;
* )
(( ++argc ))
argv =( "${argv[@]}" "$1" )
shift
;;
esac
done
http://usaturn.net/memo/shell_tech_yesorno.html
function yes_or_no_select(){
PS3="[y/n] "
while true;do
echo "yes or no."
read answer
case $answer in
y | yes)
return 0
;;
n | no)
exit 2
;;
*)
;;
esac
done
}
for i in "$@"; do
echo "$i"
done
シェル変数の設定値は実行シェルには引き継がれない
sourceと同様
新しくシェルを起動して実行する。シェル変数の設定値は実行シェルには引き継がれる。
シバンに記載されている別シェルで起動する。シェル変数の設定値は実行シェルには引き継がれる。
演算子 | 説明 |
---|---|
-a ファイル | ファイルがあれば真 |
-b ファイル | ファイルがありブロックス特殊ファイルであれば真 |
-c ファイル | ファイルがありキャラクター特殊ファイルであれば真 |
-d ファイル | ファイルがありディレクトリであれば真 |
-e ファイル | ファイルがあれば真 |
-f ファイル | ファイルがあり通常のファイルであれば真 |
-g ファイル | ファイルがありSGID(特殊なアクセス権)であれば真 |
-G ファイル | ファイルがあり実行グループIDによる所有者であれば真 |
-h ファイル | ファイルがありシンボリックであれば真(-Lと同じ) |
-k ファイル | ファイルがありステッキービットが設定されていれば真 |
-L ファイル | ファイルがありシンボリックであれば真(-hと同じ) |
-O ファイル | ファイルがあり実行ユーザIDによる所有者であれば真 |
-p ファイル | ファイルがあり名前付きパイプ(named pipe)であれば真 |
-r ファイル | ファイルがあり読み取り可能であれば真 |
-s ファイル | ファイルがありサイズが0より大きければ真 |
-S ファイル | ファイルがありソケットであれば真 |
-t FD | FD(ファイルディスクリプタ)が端末でオープンされていれば真 |
-u ファイル | ファイルがありSUID(特殊なアクセス権)であれば真 |
-w ファイル | ファイルがあり書き込み可能であれば真 |
-x ファイル | ファイルがあり実行可能であれば真 |
https://www.server-memo.net/shellscript/file_check.html
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME:+$FUNCNAME(): }'
答え
UNIXのシェルのコマンドラインでは、ハイフンひとつを標準入出力のことと読み替える習慣がある(絶対ではないが、そういう風にしている場合が多い)。
#!/bin/bash
set -ue
hello() {
exit 1
echo "aaaa"
}
main() {
local h=$(hello)
echo "bbbb"
}
main "$@"
echo "cccc"
exitを含む関数をlocal変数でうけているとだめらしい。localは戻り値が0になるらしい
local h h=$(hello)にすること
ssh -t xxx@yyy "bash -c 'export DISPLAY=192.168.1.100:0;bash'"
https://qiita.com/noexpect/items/e0e68610592874633653
awk '!colname[$1]++{print}'
rg "aaa\(" | sed "s/.*aaa(\(.*\)).*/\1/"
find $1 -name "* *" -type f -print0 | while read -d $'\0' f; do mv -v "$f" "${f// /}"; done
まずフォントがBold対応、Italic対応しているか確認する。
fc-list
で使っているフォントにBold,Italicがあるか
あったら、ターミナルが対応しているか確認する
太字
echo -e '\033[1mBold\033[0m'
斜体echo -e "\e[3mItalic"
basename $(git rev-parse --show-toplevel)
find . -mindepth 2 -maxdepth 2 -type d -exec sh -c 'ls {}/AAA {}/BBBS' ; 2>/dev/null
https://superuser.com/a/178214
atq |sort -k 6n -k 3M -k 4n -k 5 -k 7 -k 1
シングルクオートのエスケープができないためあとから置換する方法しかなさそう
local sql_command=$(echo "select start_time from test_table where start_time <= \'$datetime\' and end_time >= \'$datetime\' limit 1" | sed 's/\\//g'
convert_date() {
date +'%Y/%m/%d %H:%M' -d "$(echo ${1}00 | sed -e "s/^\([0-9]\{4\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1-\2-\3 \4:\5:\6/g")"
}
your_script | (sed -u 1q; sort)
これのsedの使い方がかっこいい。sed -u 1qで一行目だけ処理してあとをsortに回す
for ((i=0;; i++)); do printf '\r%s' $i; sleep .1; done
INFO (Use default output color)
NOTICE 36 (Front color cyan)
WARNING 33 (Front color yellow)
ERROR 31 (Front color red)
https://github.com/rcmdnk/shell-logger
( tail -f $1 & echo $! >&3 ) 3>pid | nc -l -p 9977
kill $(<pid)
tail -f $1 > >(nc -l -p 9977) &
wait $!
これが一番よい気がする
PID=$(jobs -rp)
http://yomi322.hateblo.jp/entry/2012/07/15/122530
echo ^G
tput bel
(head -n +1 sample.txt && tail -n +2 sample.txt | sort -k 2n,3n ) > sorted_sample.txt
expect
expect -c "
set timeout 5
spawn env LANG=C /usr/bin/ssh hoge@ServerName
expect "password:"
send "passwordn"
"
バックスラッシュでかわす
http://stackoverflow.com/questions/5253782/bash-problem-with-eval-variables-and-quotes
PIPESTATUS
http://kawa0810.hateblo.jp/entry/2015/01/12/213450
-
echo "
uniq .bash_history" > .bash_history
-
{ rm .bash_history && uniq > .bash_history; } < .bash_history
-
uniq .bash_history | sponge .bash_history
install moreutils
http://serverfault.com/questions/135507/linux-how-to-use-a-file-as-input-and-output-at-the-same-time
1
OS=$(lsb_release -si)
ARCH=$(uname -m | sed 's/x86_//;s/i[3-6]86/32/')
VER=$(lsb_release -sr)
2
. /etc/lsb-release
OS=$DISTRIB_ID
ARCH=$(uname -m | sed 's/x86_//;s/i[3-6]86/32/')
VER=$DISTRIB_RELEASE
3
OS=$(uname -s)
ARCH=$(uname -m)
VER=$(uname -r)
4
if [ -f /etc/debian_version ]; then
OS=Debian # XXX or Ubuntu??
VER=$(cat /etc/debian_version)
elif [ -f /etc/redhat-release ]; then
fi
5
which yum > /dev/null && { echo redhat; return; }
which zypper > /dev/null && { echo opensuse; return; }
which apt-get > /dev/null && { echo debian; return; }
set -e
trap "
mv /tmp/swap-file original-file
rm /tmp/target-file
" 0
0 or EXITは正常終了
ERRは0以外を指す
http://blog.suz-lab.com/2012/09/try-catch.html
mktempを使う
temp_file = $( mktemp )
temp_dir = $( mktemp -d )
デフォルト値を使う方法
if [ ${1:-} != "" ]( ${1:-} != "" .md);then
NOWDATE=$1
echo 1
else
NOWDATE=`date '+%Y-%m-%d'`
echo 2
fi
http://masasuzu.hatenablog.jp/entry/2013/05/01/zsh_undefined_variable
-vを使う方法(bashのバージョンが4.2以上でなければならない)
if [ -v FOO ]( -v FOO .md) ; then
echo y
else
echo n
fi
http://sousaku-memo.net/php-system/1164
ふたつある
1つ目の方法set+e
最初に
set +e
目的のコマンド
set -e
をする方法
2つ目の方法if文[...]を使わない
[...] の代わりに直接コマンドを書くと戻り値を見てくれる模様
!/bin/sh
set -e
# ifでtestも/bin/[も使わない!
if echo "$1" | grep 'a' > /dev/null
then
echo 'has a'
else
echo 'has not a'
fi
http://d.hatena.ne.jp/sasaplus1/20120621/1340207996
script_dir=$(cd $(dirname $0); pwd)
だとsourceした場合にうまく動かない
bashの場合は以下を使う
script_dir=$(cd $(dirname $BASH_SOURCE); pwd)
zshは以下
$0
ふたつとも使用出来る形式はこれ
script_dir=$(cd $(dirname ${BASH_SOURCE:-$0}); pwd)
set +x
if test -r "$upFN" -a -f "$upFN";then
fi
root_dir=(cd $(dirname $0); pwd)
Exit Code | 意味 | 例 | コメント |
---|---|---|---|
1 | 一般的なエラー全般 | $ let "var 1 = 1 / 0" | ゼロ除算などのコマンドを継続できない雑多なエラー |
2 | (Bash のドキュメントによると)シェルビルトインな機能の誤用 | $ empty_function(){} | キーワードのつけ忘れやコマンド,または権限周りの問題(あと, diffがバイナリファイルの比較に失敗した時 ) |
126 | 呼び出したコマンドが実行できなかった時 | $ /dev/null | パーミッションの問題かコマンドが executable でない時 |
127 | コマンドが見つからない時 | $ illegal_command | $PATHがおかしい時や typo した時などに起こる |
128 | exitコマンドに不正な引数を渡した時 | $ exit 3.14159 | exitコマンドは 0〜255 の整数だけを引数に取る |
128+n | シグナルnで致命的なエラー | $ kill -9 $PPID | 例では, $?は 137(128 + 9)を返す |
130 | スクリプトが Ctrl+C で終了 | Ctrl+C | Ctrl+C はシグナル2で終了する = 128 + 2 = 130(上記) |
255 | 範囲外の exit status | $ exit -1 | exitコマンドは 0〜255 の整数だけを引数に取る |