L'Isola di Niente
L'Isola di Niente » ShellScript Tips » シェルスクリプトの覚書色々

シェルスクリプトの覚書色々

# 最終更新日 2017.05.29

コメントと複数行コメント
#!/bin/sh

#echo シャープを先頭に置けば普通のコメント
: echo コロン+スペースを先頭に置いても何もおこらない

: << __HEREDOC__
    コロンとヒアドキュメントで強引に複数行コメント
    複数行をコメントアウトする正攻法手段は無いので
    エディタでの色分けは期待してはいけません
__HEREDOC__

echo 何もおこりませんでした

ヒアドキュメント
#!/bin/sh
 
# リダイレクトしたい場合は
# cat << __EOS__ >> output.txt
 
func() {
    echo バッククォートで関数も使える
}
shstr=シェルスクリプト
hdstr=ヒアドキュメント
 
cat << __EOS__
${shstr}で${hdstr}のサンプル
最初の改行は無視される、最後は echo や cat が改行する
エスケープ文字 \\ は有効
記号は \$ と \` (バッククォート)を除いて '"{[(<+-=_~!@#%^&*/ は普通に使える
`func`
__EOS__

ヒアドキュメントのインデント
#!/bin/sh
  
# <<- を使います
  
for n in 1 2 3; do
	cat <<- __EOS__
	$n: インデントしないと見栄えが気になる
	という神経質な人向け
	インデントは必ず \t で行ってください
	__EOS__
done

コマンドの実行はするけど結果の出力はしない
#!/bin/sh

echo 出力されない > /dev/null 2>&1
# 実行はされていることの確認
gnome-terminal > /dev/null 2>&1

コマンドの存在を確認してから実行
#!/bin/sh

# 各自で書き換えしてね
cmd=gnome-terminal

if type $cmd > /dev/null 2>&1; then
    $cmd
else
    echo $cmd コマンドは存在しません
fi

無限ループ
#!/bin/sh

# while true は while : でいい

echo y で終了
while : ; do
    read -n 1 res
    if test $res = "y"; then
        break
    fi
done

ファイル名色々
#!/bin/sh

# 半角空白や日本語があっても問題無いようです
# basename, dirname というコマンドもある

pic="/home/oyaji/pictures/name.jpeg"

echo ${pic%/*}
#=> /home/oyaji/pictures

echo ${pic##*/}
#=> name.jpeg

echo ${pic%.*}
#=> /home/oyaji/pictures/name

echo ${pic##*.}
#=> jpeg

Windows から持って来たファイルの変換
#!/bin/sh

# iconv で /usr/lib64/gconv にあるライブラリ同士は全部変換できる
# しかし iconv だけでは改行コードを LF に変換してくれない
# dos2unix は utf-8 の BOM 外しにも使える

iconv -f CP932 -t UTF-8 932.txt | dos2unix > utf8.txt

# CR を削除するだけならこんな方法もある
tr -d '/r' < cr_lf.txt

端末入力とパイプ入力で振り分け
#!/bin/sh

# stdin のファイルディスクプリタはゼロ

if [ -t 0 ]; then
    echo 何か入力してください
    read text
    echo $text が入力されました
else
    echo パイプから以下を受け取りました
    while read line; do
        echo $line
    done
fi

インクリメント
#!/bin/sh

# デクリメントは --

count=0
while (( count < 1000 )); do
    (( count++ ))
done
echo $count
#=> 1000

キッチンタイマー
#!/bin/sh
 
# カップラーメン用にどうぞ
 
read -p 完成までの残り時間を秒で指定: count
echo 止めるには Ctrl+C
 
while (( count > 0 )); do
    printf "残り%02g分%02g秒  \r" $(( count / 60 )) $(( count % 60 ))
    (( count-- ))
    sleep 1
done
echo できあがりぃ~

一覧表作成
ls -l > ファイル一覧.txt
find -name "*" > ファイル構造.txt
tree > ディレクトリツリー.txt
df -h > ディスク一覧.txt

区切り文字の変更
#!/bin/sh

# $IFS は区切り文字を定義する変数
# デフォルトは スペース、タブ、改行(0xff,0x09,0x0a)

_IFS=$IFS
IFS=,
csv=カンマ,区切りの,テキスト

for s in $csv; do
    echo $s
done

# 元に戻す
IFS=$_IFS

16進数, 8進数
#!/bin/sh

# 16進数の計算 0x**
echo $(( 0xff * 2 ))
#=>510

# 8進数の計算 0**
echo $(( 010 * 2 ))
#=>16

一行上に出力
#!/bin/sh

# \033[数値A で戻りたい行数の数値
# \033[0J    でカーソル以降の行を削除

echo いくぞー

for s in いーち にー さーん だぁー!
do
    sleep 1
    printf "\033[1A\033[0J"
    echo $s
done

色分け表示
#!/bin/sh

# http://linuxjf.sourceforge.jp/JFdocs/Bash-Prompt-HOWTO-5.html

printf "\033[32m緑色おおおお\n"
printf "\033[31m赤色おおおお\n"
# 戻す
printf "\033[39m"

ドットコマンド(source コマンド)
#!/bin/sh

# dot_command というファイルを作る
cat << _EOS_ > dot_command
#!/bin/sh
CHILD=子変数
echo \$OWNER
_EOS_

# 上記に +x パーミッションを与える
chmod +x dot_command

# シェル変数を定義する
OWNER=親変数

echo 普通に実行(サブシェルで動く)
# 親で定義した変数は参照でない
# 親シェルからサブシェルの変数も参照できない
# 環境変数にすればサブシェルからも参照可能

./dot_command
echo $CHILD
#=>
#=>

echo ドットコマンド(このシェルで動く)
# シェルで定義した変数は参照できる
# スクリプト内の変数も参照できる
# source ./dot_command でもいい

. ./dot_command
echo $CHILD
#=>親変数
#=>子変数

for 文の結果をリダイレクト
#!/bin/sh

# /usr/bin の中身を $HOME に出力するサンプル
# done の後ろに > で for 文の結果をリダイレクト

cd /usr/bin

for name in `ls`; do
    echo $name
done > ~/output.txt

拡張子の一括変換
#!/bin/sh

# デジカメからコピーした *.JPEG を *.jpg に変換

for PIC in *.JPEG; do
    mv $PIC ${PIC%JPEG}jpg
done

デフォルト引数
#!/bin/sh

# ${:-} で指定
# 下記は引数があれば引数を、無ければデフォルト引数を表示

arg=${1:-引数が無いよ}
echo $arg

数値順ソート
#!/bin/sh

# 先頭が数値なら文字列交じりでもイケる

printf "123\n45\n7\n89" > num.txt
sort -n num.txt
: << __OUTPUT__
7
45
89
123
__OUTPUT__

ユーザーディレクトリ(デスクトップ等)パスの取得
#!/bin/sh

# Linux はドットコマンドで user-dirs.dirs の指定を取り込み
. ~/.config/user-dirs.dirs
echo $XDG_DESKTOP_DIR


# Mac は AppleScript から
desktop=`osascript -e "POSIX path of (path to desktop folder)"`
echo $desktop

間接参照
#!/bin/sh

# ${!prefix*} 又は ${!prefix@}
# にて該当変数名をブレース展開してくれる
# 又文字列から下記のように変数を参照することもできる

GF_top='心美 文緒 くおえ'
GF_loli='苗 睦 桃子'

echo ${!GF_*}

for gf in ${!GF_*}; do
    for s in ${!gf}; do
        echo $s
    done
done

大文字小文字を区別しないで画像拡張子を選択
#!/bin/sh

# shopt で大文字小文字を区別しないようにする
shopt -s nocasematch

PICS="a.Jpg b.jpeg c.png D.JPEG e.mjpeg f.gif jpg.txt"

for fn in $PICS; do
    [[ $fn =~ \.(jpe?g|png|gif)$ ]] && echo $fn
done

自作スクリプトの実行時間を計る
#!/bin/sh

# sh でも python でも何でもいい

time python3 hoge.py

マシン情報
#!/bin/sh

echo \# ホスト名
cat /etc/hostname

echo \# ディストリビューション名
cat /etc/system-release

echo \# カーネル名
cat /proc/version

echo \# CPU 名
cat /proc/cpuinfo | grep name
Copyright(C) sasakima-nao All rights reserved 2002 --- 2017.