shell script a bit



ファイル名一括変換

somma-01(02,03,...).jpg があったとして、 それを winscp-01(02,03,...).jpg に変換したい。

$for f in *.jpg
>do
>mv $f `echo $f | sed 's/somma/winscp/g'`
>done

連番でいろいろ

【基本編】
  1. 画像データのリサイズ
    $ for f in *.jpg*
    > do
    > convert -geometry 1024x768 $f ~/hoge/hogehoge/$f
    > done
    

  2. 画像形式の変更
    cd ~/hoge/hogehoge/
    $ for f in *.jpg*
    > do
    > convert -geometry 25%x25% $f ${f%jpg}png
    > done
    

  3. 連番でリネーム
    $ declare -i i=1
    $ for f in *.jpg*
    > do
    > mv $f $i.jpg
    > i=i+1
    > done
    

参照url: windowsユーザーに教えるLinuxの常識 その7

【応用編】
今度は連番をふりながら画像サイズを換える。その際の連番は 001 から 始まる。

$ declare -i i=1
$ for f in *.jpg
>do
>convert -geometry 50%(50% x 50%) $f ./hoge/00$i.jpg
>i=i+1
>done

文字列一括置換!

シェル・スクリプトと聞いて、やってみたかったのはまずこれ。
なんてったって、エディタで一々中身を確認しなくても文字置換を行えてしまう。
しかも複数のファイルを一括で。 …これだけのために Linux(unix) を使ってもいいんじゃないか!
と思えるくらい(そりゃ、窓でもそういったソフトはあるだろうけど、 それだけのために落としてくる…なんて、ね)

さて、余談はさておき、本題へ。
解説なんて面倒だから後回し。ともかくこれを見よ。

これで、完璧に任意のディレクトリにある".tex"文書のなかの 「更正」という文字がすべて「更生」という文字に一括で置換されるのだ。

$ hoge/	                         … 当該のディレクトリへ移動しておく
$ hoge/ for f in *.tex           … for コマンドで処理する拡張子を決定
> do                             … 一括処理開始を宣言
> sed 's/更正/更生/g' $f > $f.new … sed で .tex内の「更正」を「更生」に一括で変更。
                                    その後一時的に .tex.newというファイルを作る
> mv $f.new $f                   … .tex.new を元の .tex に書き換える
> done                           … 実行
$ hoge                           … cat hoge.tex か何かで確認。感動でむせび泣いてくれ
さて、肝になる sed のコマンドをまとめておくと次のようになる。
概略 : 行単位でのテキスト編集
書式
  1. sed s/対象文字列/置換文字列/ ファイル : 指定したファイルの各行から文字列を検索して最初に一致した文字列を置換する
  2. sed s/対象文字列/置換文字列/g ファイル : 指定したファイルの各行から文字列を検索して一致した文字列を全て置換する
  3. sed 's/対象文字列/置換文字列/' ファイル : 検索文字列に正規表現を含む場合
  4. sed y/対象文字/置換文字/ ファイル : 対象文字を置換文字で置き換える(一文字単位)
さしあたり 3. を覚えておけば最強。 (というかシングルクウォートは癖にしておいた方がよい)

あと、sed で忘れちゃならないのが リダイレクト ">"による ファイルへの書き出しだ。
これは当り前なのか、なかなか思い付くまで苦労したよ。
…そう、別ファイルに書き出さないと何もしないのと同じなんだよな。
リダイレクト… うーむ便利だ。
ただ、リダイレクトでそのまま $f 関数に入れてしまうとファイルが空になってしまう ので注意が必要。
これには mv で元に戻す(適当にリダイレクトで .new とかつけておいて、 mv で $f に書き換える)

画像移動自由自在

まだ途中だが、ファイル名から拡張子(など)を除いた値を吐き出す "basename" など というコマンドが覚えた。 また括弧にもいろいろ意味があるのだなぁ(まだ調べていない)、と感心した。

ともかく、今回やろうとしたことは、ある連番の振られた画像ファイルから、共通した要素でディレクトリを掘り、そこに当該の画像を放りこむ、という単純なものだ。
…が、苦労したわ。あいもかわらず。

…まだ途中…
0000-0000-0045-0001.jpg 〜 0000-0000-0045-0006.jpg, 0000-0000-0050-0001 〜 000-0000-0050-0006.jpgという12個の画像ファイルがあり、それぞれ下12桁(0000-0000-0045, 0000-0000-0050)のディレクトリを掘り、すべての画像をそこに割振り、放りこむ。

for f in *0001.jpg
> do
> mkdir `basename $f -0001.jpg` … 「'」ではなく「`」という点に注意
> for g in *.jpg
> do cp $g `basename $f -0001.jpg`
> done
> done

メニュー形式

西洋美術館納品サーバでやったこと。
基本的にサーバというものは止めるものではない。 しかし、世の中何が起きるか分からない。 …例えば停電とか。

サーバなんぞ知らん人(職員)にも緊急対応できるように、 ユーザ:menu を作り、ログイン時には自動的に「再起動とシャットダウン」ができる スクリプト menu.sh を実行するようにした。

手順は以下の通り。

  1. # adduser menu
  2. # cd /home/menu
  3. # emacs menu.sh
  4. # chown menu.menu menu.sh
  5. # su menu
  6. $ chmod +x menu.sh
  7. $ exit (su 抜ける)
  8. # visudo
  9. # exit (su 抜ける)
  10. $ vi .bash_profile

では、まず menu.sh から。
3.menu.sh


#!/bin/sh

function yesno () {
	read -n 1 -p $1 A
	echo
	if [ $A = 'Y' -o $A = 'y' ]; then
		return 0
	fi
	if [ $A = 'N' -o $A = 'n' ]; then
		return 1
	fi
	return 2
}

function anykey () {
	read -n 1 -p '何かキーを押してください'
}

ER=1

while [ $ER = 1 ]; do
	clear
	echo 管理メニュー
	echo 1. 再起動
	echo 2. シャットダウン
	echo 3. メニュー終了
	read -n 1 -p '番号を入力> ' A
	echo
	case $A in
		1)
			echo マシンを再起動します
			if yesno '再起動しますか(Y/N)> '; then
				ER=0
				sudo shutdown -r now
			else
				ER=1
				echo 再起動を取り消します
			fi
		;;
		2)
			echo マシンをシャットダウンします
			if yesno 'シャットダウンしますか(Y/N)> '; then
				ER=0
				sudo shutdown -h now
			else
				ER=1
				echo シャットダウンを取り消します
			fi
		;;
		3)
			echo メニューを終了します
			ER=0
		;;
		*)
			echo 入力した番号が範囲外です
		esac
	done

次にある特定のコマンドだけをパスワードなしで実行してもらうための 8.visudo
# /etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# See the man page for details on how to write a sudoers file.
#

# Host alias specification

# User alias specification
User_Alias FULLTIMERS=menu

# Cmnd alias specification
Cmnd_Alias ADMIN=/sbin/shutdown

# User privilege specification
root    ALL=(ALL) ALL
hujioka ALL=(ALL) ALL
eito    ALL=(ALL) ALL
FULLTIMERS ALL=NOPASSWD:ADMIN
~

.bash_profile

if [ $TERM = "linux" ]; then
	clear
	exec jfbterm -q -e /home/menu/menu.sh
fi