新山がふだん使っているスクリプト (shell, perl) をまとめたもの。
あなたの環境でそのまま動くとは限りません。
bash を使っているときは、
`basename $i`
のかわりにシェルの変数置換:
${i/*\//}
が使える。
拡張子だけを削りたいなら
${i/.*/}
なども可能
(ただしこれは abc.def.html
を abc
のみにしてしまうので注意)。
lessdir
-
ファイルに対しては less、ディレクトリに対しては ls を起動
(実際には新山は「l
」という一文字のコマンドにしている、
less
のかわりにいつもこれを使っている)
#!/bin/sh # 環境変数 $PAGER に値が設定されてない場合は、 # デフォルトとして less を使う。 PAGER=${PAGER-less} # このスクリプトに与えられた引数を見る。 if [ $# -eq 0 ]; then # 引数がない場合、hoge | lessdir のように起動されたのだと考える。 # $PAGER を起動そのまま起動しておしまい。 # あとはこいつが、このスクリプトの標準入力を継承するだろう。 exec $PAGER elif [ -d "$1" ]; then # 最初の引数がディレクトリを表していれば、 # ls モードと解釈する。引数ぜんぶ (最初のも含め) ls に渡しておしまい。 exec ls -F $* else # それ以外なら、ページャとして扱われたのだと考える。 # 引数ぜんぶ (最初のも含め) $PAGER に渡しておしまい。 exec $PAGER $* fi
lessdirauto
- lessdir の改良版。端末の大きさに応じて cat と
less を使い分ける
(表示するファイルすべてを一時的に /tmp
以下に保存するので、
あまり長いファイルの表示には向いていない)
#!/bin/sh # 一時ファイルの名前を変数 t に入れる # この名前は重複してはまずいので、とりあえず$$を使って # プロセスIDを含めておく。 t=/tmp/L$$ # 途中でこのプロセスが異常終了したときに、 # 一時ファイルを自動的に消すようにtrapを仕掛ける。 cleanup() { rm $t; exit 1; } trap cleanup INT HUP TERM; # 実際に表示する内容を、$t で表される一時ファイルに入れる。 # この部分は lessdir と同じだが、exec は使わない。 if [ $# -eq 0 ]; then # 引数がない場合、hoge | lessdirauto のように起動されたのだと考える。 # cat にこのスクリプトの標準入力を継承させ、入ってきたものを全部 # $t に吐かせる。 cat > $t elif [ -d "$1" ]; then # 最初の引数がディレクトリを表していれば、 # ls モードと解釈する。ls の結果をまず全部 $t に吐かせる。 ls -oF $* > $t else # それ以外なら、ページャとして扱われたのだと考える。 # 表示するファイルを全部 $t に吐かせる。 cat $* > $t fi # (端末の行数 - 2) を変数 height に入れる。 # stty size は「25 80」のように「行数 桁数」の順で出力するので、 # それをまずいったん配列に入れて、最初の要素 ($1) だけを取り出すことで # これが実現できる。あとは expr に渡して 2 だけ引いてやる。 # (stty を普通に呼ぶと、標準入力がパイプからのリダイレクトであるときに # うまく動作しない。そこで、/dev/tty をリダイレクトすることで無理矢理端末を # 見させるようにする。) set -- `stty size </dev/tty` height=`expr $1 - 2` # 一時ファイル $t の行数を変数 lines に入れる。 # wc は「12 435 7880 filename」のように「行数 単語数 文字数 ファイル名」の # 順で出力するので、これも最初の要素だけを取りだせばよい。 set -- `wc $t` lines=$1 # 表示する行数 (lines) が端末の行数 (height) より多ければ less -X を、 # そうでなければ cat を使う。 if [ $lines -gt $height ]; then less -X $t; else cat $t; fi # 最後に一時ファイルを消して、おしまい。 rm $t;
showhelp
- コマンドのヘルプを表示する
(よくコマンドによっては、オプションの長いヘルプを標準エラー出力に
吐くので、less で見ようとしても消えてしまう。このコマンドは
showhelp cdparanoia
などとやると、
単に cdparanoia --help
を実行してその標準出力および
標準エラー出力を lessdirauto
(上記参照) に流すだけのもの)
#!/bin/sh # 与えられたコマンド文字列に --help という引数をつけて実行する。 # このとき標準エラー出力を標準出力にリダイレクトし、エラーメッセージも # 一緒にパイプを流れるようにする。 $* --help 2>&1 | lessdirauto
querycode
- ファイルの漢字コードを判定する(新山は自分の書いた web ページの漢字コードが 全部 jis (iso-2022-jp) かどうかをチェックするのにこれを使っている)
#!/bin/sh # すべての引数についてチェック。 for fname in $*; do # 安全のため、そのファイルが「普通の」ファイルであることを確認する。 if [ -f $fname ]; then # ここで nkf を使って、そのファイルを各漢字コードに変換してみる。 # 変換結果と元のファイルを cmp で比較し、同じならば # nkf に指定した漢字コードを使っていることになる。 # ファイルに日本語が含まれていない場合は、 # デフォルトで jis と判定される。 # これが嫌な場合は nkf の順番を変えること。 if nkf -j $fname | cmp -s $fname; then # ファイル名を一緒に出力してもいいかも。 echo jis elif nkf -s $fname | cmp -s $fname; then echo sjis elif nkf -e $fname | cmp -s $fname; then echo euc else # どの漢字コードでもなかった場合。 echo unknown fi fi done
#!/bin/sh exec rsync -Cauvbz --delete --backup-dir ~/.old \ --exclude 'LOCAL' --exclude 'local' \ --include '*.obj' --include '*.Z' \ $*
get host1:dir
とすると、host1 上の ~/dir の変更点が
ローカルな ~/dir に反映される。
put host1:dir
とすると、ローカルな ~/dir の変更点が
host1 上の ~/dir に反映される。
2つのマシンで作業するときに楽。
#!/bin/sh cd for i in $*; do h=`expr "$i" : '\(.*\):'` d=`expr "$i" : '.*:\(.*\)'` if [ ! "$d" ]; then d=.; fi echo $d if [ "$h" -a -d "$d" ]; then case $0 in *get) rs "$h:$d/" "$d/";; *put) rs "$d/" "$h:$d";; esac fi done
#!/usr/bin/perl open(IN, "od -tx1 -Ax @ARGV |"); while(<IN>) { chop; @f=split(' '); print $_," "; shift(@f); $s=''; foreach $i (@f) { $c=pack("H2",$i); $c='.' if (ord($c)<32); $s.=$c; } print " " x (16-@f); print "$s \n"; }
ときどき、 tar のソースツリーなどを展開すると パーミッションが 444 になっていてむかつくため。
#!/bin/sh find $* -type f | xargs chmod 644 2>/dev/null find $* -type d | xargs chmod 755 2>/dev/null
ucspi-stcp 使用。 プロトコルのチェック等に。
(まずこのスクリプト waitio をインストールしておく必要がある)
#!/usr/bin/perl open(TTYIN,"<&6"); binmode(TTYIN); select(TTYOUT); $|=1; open(TTYOUT,">&7"); binmode(STDIN); select(STDOUT); $|=1; $rin=''; vec($rin,fileno(STDIN),1)=1; vec($rin,fileno(TTYIN),1)=1; do { $n=select($rout=$rin,undef,undef,undef); if (vec($rout,fileno(STDIN),1)) { sysread(STDIN,$_,1024); s/\r//g; print TTYOUT $_; } if (vec($rout,fileno(TTYIN),1)) { exit if (!sysread(TTYIN,$_,1024)); s/\n/\r\n/g; print STDOUT $_; } } while(1);
(サーバ側)
#!/bin/sh p=${1-1111} echo "waiting on $p..." exec env - PATH=$PATH tcpserver -vRHl0 -c1 0 $p waitio 6</dev/tty 7>/dev/tty
(クライアント側)
#!/bin/sh if [ $# -lt 2 ]; then echo "usage: client host port"; exit 1; fi exec tcpclient -RHl0 -- $1 $2 waitio
stwm 専用。AucTeX に比べて何がよいかというと、ウインドウマネージャと 結託しているので、何度 xdvi を実行しても余計なウインドウが開かないこと。 後述の ftime 使用。
#!/bin/sh # atex wmcmd=stwmcmd bibtex=${BIBTEX:-jbibtex} latex=${LATEX:-platex} xdvi=${XDVI:-xdvi} mode=dvi # print usage usage() { echo 'usage: atex [-fpdcj] filename -f: force compile -c: compile only -p: preview only -d: cleanup -D: cleanup including ps -j: use jlatex209 -P[printer]: print' exit 1 } # check if it is new isnew() { test `ftime -m $1` -gt `ftime -m $2`; return; } # clean up cleanup() { if isnew $1.tex $1.aux; then echo "cleanup $1.aux"; rm $1.aux $1.bbl $1.blg $1.toc fi rm $1.log } # preview preview() { if [ "$xdvi" -a "$wmcmd" ]; then # run xdvi icon=`$wmcmd -t $xdvi q iconified` if [ "$icon" ]; then # xdvi already running if [ $icon = 0 ]; then # xdvi not iconified $wmcmd -t $xdvi stack 1 $wmcmd -t $xdvi warp else # xdvi iconified $wmcmd -t $xdvi iconify 0 fi else # xdvi not running $xdvi $fname.dvi >/dev/null 2>&1 & fi fi } # compile compile() { $latex $fname if [ `grep '^LaTeX Warning: Citation .*undefined' $fname.log | wc -l` -ne 0 ]; then $bibtex $fname $latex $fname fi if [ `grep '^LaTeX Warning: Citation .*undefined' $fname.log | wc -l` -ne 0 ]; then $bibtex $fname $latex $fname fi } # print print() { dvips $fname if [ $printer = 0 ]; then mpr $fname.ps else lpr -P$printer $fname.ps fi } # get option set -- `getopt P:fpdDcj $*` if [ $? != 0 ]; then usage; fi while [ "$1" != -- ]; do case $1 in -f) mode=force;; -p) mode=preview;; -d) mode=clean;; -D) mode=cleanps;; -c) mode=compile;; -j) latex=jlatex209;; -P) mode=print; printer=$2; shift;; esac shift done shift if [ ! "$1" ]; then usage; fi cd `dirname $1` fname=`basename $1 .tex` # main case $mode in compile) cleanup $fname compile;; preview) preview;; clean) rm -f $fname.dvi $fname.log $fname.aux $fname.bbl \ $fname.blg $fname.toc;; cleanps) rm -f $fname.dvi $fname.log $fname.aux $fname.bbl \ $fname.blg $fname.toc $fname.ps;; force) if compile; then preview fi;; dvi) if isnew $fname.tex $fname.dvi; then cleanup $fname if compile; then preview fi else preview fi;; print) if isnew $fname.tex $fname.dvi; then clean $fname if compile; then print fi else print fi;; esac
フロッピーに生のtarを書きこむスクリプト。 むかしは Mac で SUNTAR を使っていたため。
#!/bin/sh case `hostname` in godot) dev=/dev/fd0;; # linux snow) dev=/dev/fd0a;; *) echo "$0: not supported on this machine."; exit;; esac; cmd=$1; if [ ! "$cmd" ]; then cmd=dir; else shift; fi; case $cmd in add) exec /usr/local/bin/tar -L 1440 -r -v -f $dev $*;; new) exec /usr/local/bin/tar -L 1440 -c -v -f $dev $*;; ext) exec /usr/local/bin/tar -L 1440 -x -v -f $dev $*;; dir) exec /usr/local/bin/tar -L 1440 -t -v -f $dev;; *) echo "usage: $0 {add,new,ext,dir} file ..."; esac;
sed を使っています。
#!/bin/sh if [ $# -lt 2 ]; then echo 'usage: formv s/pat1/pat2/ file ..'; exit 1; fi s=$1 shift for i in $*; do j=`echo "$i"|sed "$s"` echo $i "->" $j; mv $i $j done
シェルスクリプトで make もどきをしたい場合に使う。
#!/usr/local/bin/perl if ($ARGV[0] eq '-a') { @_ = stat($ARGV[1]); $a = $_[8]; } elsif ($ARGV[0] eq '-m') { @_ = stat($ARGV[1]); $a = $_[9]; } elsif ($ARGV[0] eq '-c') { @_ = stat($ARGV[1]); $a = $_[10]; } elsif ($ARGV[0]) { @_ = stat($ARGV[0]); $a = $_[9]; } else { $a = time(); } if (! $a) { $a = 0; } print "$a\n";
日本語の検索エンジンや掲示板に入力するときはコレ。
#!/bin/sh export SHELL; SHELL=tcsh kterm -xrm 'KTerm*VT100*translations: #override Ctrl<Key>j: begin-conversion(JAPANESE_CONVERSION)\n' \ -T jlynx -n jlynx -geom 80x50-0-0 -e /usr/local/bin/lynx &
拡張子を見て ps, ps.gz, pdf, テキストを区別し印刷する。
#!/bin/sh # lpo: # -P printer : speficy printer # -m : speficy twocolumns # -1 : onecolumn # -p : onecolumn, portlait-duplex # -2 : twocolumn, landscape-duplex set -- `getopt P:m1d2 $*` if [ $? != 0 ]; then echo "usage: lpo [-Pprinter] [-m1d2] [file ...]" fi p=pst m=0 a=-np while [ $1 != -- ]; do case $1 in -P) shift; p=$1;; -m) m=1;; -1) m=0; a=-p; p=ps;; -p) m=0; a=-p; p=psdp;; -2) m=1; p=psdl;; esac shift; done shift; spool() { if [ $m = 1 ]; then psmulti -nodecor $* | lpr -P$p $*; else lpr -P$p $*; fi } if [ $# = 0 ]; then spool; exit; fi for i in $*; do case $i in *.ps) spool $i;; *.ps.gz) gzip -dc $i | spool;; *.pdf) t=/tmp/prt.$$ acroread -toPostScript -size a4 -shrink -pairs $i $t spool $t rm $t;; *.dvi) /usr/local/bin/dvips -f $i | spool;; *) if [ "X$a" = "X-np" ]; then m=0; fi a2ps $a $i | spool;; esac done
むかし、Mac でテキストを書いていたときに使っていたんよ。
#!/bin/sh if [ ! "$1" ]; then echo "usage: mj filename ..."; exit; fi while [ "$1" ]; do if [ \( -h "$1" \) -o \( ! -f "$1" \) ]; then echo "mj: $1 is not regular file."; else echo "mj: convert: $1" f=/tmp/mj.$$; mv $1 $f; tr '\^M' '\ ' < $f > $1; rm $f; fi; shift; done
メールを書くのに .signature ファイルは使っていません。 かわりにこれを使ってファイルをバッファに取りこみます。 こうすると切り換えもできて便利。
#!/bin/sh case $1 in x) echo '-- 東京工業大学 情報理工学研究科 計算工学専攻 新山 祐介 euske@cl.cs.titech.ac.jp';; e) echo 'SHINYAMA Yusuke -- Dept. of Computer Science, Tokyo Inst. of Technology, 2-12-1, Ookayma, Meguro-ku, Tokyo, 152-8552, JAPAN E-MAIL: euske@cl.cs.titech.ac.jp FAX: +81 3-5734-2915';; *) echo '-- 新山 祐介 euske@cl.cs.titech.ac.jp';; esac;
(で、 .emacs には次のように書いておく)
;; signature ;; (defun sig () (interactive) (call-process "sig" nil t t)) (defun xsig () (interactive) (call-process "sig" nil t t "x")) (defun esig () (interactive) (call-process "sig" nil t t "e"))
デフォルトで xterm でなくて kterm を起動する。あと、プロセス ID を 表示するのとエラー出力を ~/.xsession-errors に追加するのが便利。
#!/bin/sh if [ ! "$*" ]; then echo "Usage: xrsh <hostname> [command ...]"; exit 1; fi if [ ! "$DISPLAY" ]; then echo "xrsh: Can't open display."; exit 1; fi target=$1; shift; program="$*"; if [ ! "$program" ]; then program="kterm -T kterm@$target -n $target"; fi; errorfile="$HOME/.xsession-errors"; rsh $target "sh -c 'SHELL=$SHELL DISPLAY=$DISPLAY $program >>$errorfile 2>&1 & echo \"xrsh: $target: \$!\"'";