Skip to main content

Posts about shell

other tips for scripting

remove all carriage returns

cat file | tr -d '\n'

url encoding and decoding

echo 'http://example.com' | nkf -WwMQ | sed 's/=$//g' | tr = % | tr -d '\n'

echo http%3A%2F%2Fexample%2Ecom | nkf -w --url-input

handle files which name may include spaces

find dirname -print0 | xargs -0 ls

convert character code from sjis to UTF8

iconv -f SJIS -t UTF8 oldfile > newfile

set positional parameter

$ set -a -b foo bar
$ echo $# $@
2 foo bar

$ set -- -a -b foo bar
$ echo $# $@
4 -a -b foo bar

w | awk '$1~/'$(whoami)'/{print}' | while read line; do
  set ${line}; echo USER:$1 TTY:$2 FROM:$3 LOGIN@:$4 IDLE:$5 JCPU:$6 PCPU:$7 WHAT:${*:8}
done

color text

esc=$(printf '\033')

color="${esc}[36m" # cyan
bold="${esc}[1m"
underline="${esc}[4m"
colorbold="${esc}[1;36m"
colorunderline="${esc}[4;36m"
reset="${esc}[0m"

echo "${color}color text${reset}"
echo "${bold}bold text${reset}"
echo "${underline}underline text${reset}"
echo "${colorbold}color bold text${reset}"
echo "${colorunderline}color underline text${reset}"
echo normal text
color foreground background
Black 30m 40m
Red 31m 41m
Green 32m 42m
Yellow 33m 43m
Blue 34m 44m
Purple 35m 45m
Cyan 36m 46m
White 37m 47m

sample of simple bash scripts

ファイルバックアップスクリプト

引数に与えられたファイルを3ケタの連番をつけてコピーする。 まだいま一ついけてない。

gistの引用のテストをかねて。

bash

bashスクリプト等でよく使う機能の利用パターンを記載。

trap

When the script exits, remove tmpfile

tmpfile=/tmp/tmpfile.$$
trap "rm ${tmpfile}" EXIT

basename, dirname

use script file name and directory in the script

echo $(basename $0 .sh)
echo $(dirname $0)

pushd, popd

pushd、popdは標準出力にメッセージを吐く。スクリプトで使用する際は不要なので捨てる。

pushd . > /dev/null
cd dir
:
popd    > /dev/null

read

標準入力からの入力を変数dummyへ入れる。 (-pでプロンプトを指定。-sを指定するとエコーバックしない)

read -p "input? " [-s] dummy

比較演算

条件を満たせばtrue

演算子 説明
-z 文字列の長さ0
-n 文字列の長さ1以上
-s ファイルサイズが1以上

if

文字列の比較

if [ $str = "hoge" ]; then
:
else
:
fi

case

case "$?" in
  0)
    echo ok
    ;;
  1)
    echo ng
    ;;
  *)
    echo error
    ;;
esac

for loop

for file in /etc/ssh/ssh_host*key* ; do
:
done

while loop

条件がtrueの時だけ実行する。

while true; do
:
sleep 300
done

全ての引数に対して処理を実行する。

while [ $1 ]; do
echo $1
shift
done

while とread

while read line; do
echo $line
done < filename

または

cat filename | while read line; do
echo $line
done

printf

printf 'INSERT INTO mytable (temprature, humidity) VALUES (%f, %f);' 20.0 50.0 | sqlite3 database.db

組み込みコマンドgetoptsの使い方の例

#! /bin/bash

while getopts "hw:" opt; do
  case ${opt} in
    h)
      echo usaage
      exit
      ;;
    w)
      dow=${OPTARG}
      ;;
  esac
done
shift $((OPTIND - 1))

while [ $1 ]; do
  :
  shift
done

indirection reference

using shell

key=slackpkg
pkg_slackpkg=skackware
myos=pkg_${key}
echo ${!myos}

using eval

pkg_slackpkg=slackware
key=slackpkg
eval myos=\"\${pkg_${key}}\"
echo ${myos}

when variable is array

pkg_apt=(debian ubuntu raspbian)
pkg_yum=(rhel fedora centos)

for key in apt yum; do
  echo ${key}
  for i in `seq 0 2`; do
    eval myos=\"\${pkg_${key}[i]}\"
    echo ${i}: ${myos}
  done
done

その他

スクリプトの改行文字をCR+LFで書くと、CRが(shebang等の)コマンド(の一部)として認識され、実行エラーとなる。 スクリプトの改行文字はLFで書く。

$ bash myscript.sh
: command not found
$ chmod +x myscript.sh
$ ./myscript.sh
-bash: ./myscript.sh: /bin/bash^M: bad interpreter: そのようなファイルやディレクトリはありません

When shebang is omitted though it has executable permission (+x), when it called without shell command it may show below error message

exec user process caused "exec format error"

rename the file using a part of original file name.

$ ls | tail -4 | awk -F_ '{print "mv",$0, "foo_"$4}'