役に立つシェルスクリプト群

Last-modified: 2015-11-08 (日) 22:11:16

(2011-6-14追記)最近はこちらのページにポッドキャスト・動画ダウンロード、携帯プレーヤー関係等のスクリプトを掲載しています。私にとってはiTunesの代わりです。
これなんかは動的な文字列リストをGUIで選択するスクリプトです。


初出 2006-8-18
最終更新 2015-10-29
私自身が重宝している自作シェルスクリプトを紹介します。
一応「役に立つ」と謳っていますが、ニッチな機能なスクリプトばかりです。実態は「一部の人だけに役に立つスクリプト群」です。
全て自由に使って頂いて結構です。
個々のスクリプトを丸ごと掲載するスタイルの為、ページ全体で重複部分が多くならないように、意識的に書式にバラエティを持たせてあります。たとえば文字列の切り出しはcut,awkのsubstr,bashの機能等、様々な方法を適当に使用しています。
 

Ubuntuの場合、デフォルトではsh=dashなので"if ["を使っている個所は手直しが必要です。
私の場合は手っ取り早くこのように

$ cd /bin ; sudo ln -sf bash sh

sh=bashに変更してしまって対応することが多いです。(2010-3-4追記)最近はやらないです。ただし今後作成するものについてはbash専用を除いてはPOSIX準拠を(出来れば)心がけたいと思っています。

 

ファイルのダウンロード用リンク(他のスクリプトは画面からコピペしてください)


少し並べ替えました。

(おまけ)下の応用で私が実際に使用しているもの

dircp.shと似すぎていてあまりに冗長なので、おまけとして、期間限定(のつもり)でページ末尾先頭に掲載します。

[tip] setup-bkup.sh(指定ディレクトリ以下のカスタマイズした部分を一気に抜き出して保存)

おまけコーナーに記載しますが、もしかすると意外に役に立つ人が本ページで一番多いかもしれません。

よく、OSインストール後の細かなカスタマイズなどを詳細に記録して、"備忘録"や"メモ"というタイトルでwebに公開している方がいます。私はそんな面倒なことできねえよってことで、もっと簡単な方法を用いています。

  • カスタマイズ前にディストリビューションオリジナルのファイルを*.origという名前でバックアップしておく
    というルール一つを守ることだけで変更の記録を残しています。

例えばsmb.confというファイルをsmb.conf.origという名前で同じ場所に保存しておくわけです。そうすれば*.origというファイルがあることがカスタマイズしたことの目印になります。全てのカストマイズが終了した後に、

# setup-bkup.sh  /  ubuntu-setup

みたいな感じで実行すれば、ディレクトリubuntu-setupが作成され、その中には、

ubuntu-setup/----etc/----sysctl.conf
            |       |
            |       |----sysctl.conf.orig
            |       |
            |        ----samba/----smb.conf
            |                 |
            |                  ----smb.conf.orig
            |
            |----home/----disklessfun/----.bashrc
                                     |
                                      ----.bashrc.orig

みたいに、ディレクトリ構造を持ったまま、カストマイズした部分だけを抜き出すことができます。tipsですが、新規追加したファイルも一緒に抽出されるように、たとえば.vimrcを新規追加したなら、同じ中身の.vimrc.origも同時に追加しておきます。こうすれば追加したファイル・更新したファイルの双方の記録を残すことができます。
ディレクトリのプロパティは元のものがコピーされます。(必要のない機能かもしれませんが)

 

そして、setup-restoreのような名前でsetup-bkup.shのシンボリックリンクを作成しておき、

# setup-restore  ubuntu-setup  /

みたいな感じで実行すると、 バックアップしておいた設定を反映することができます。同じようなOSセットアップを繰り返す場合には便利です。
diffで変更チェックをおこなっています。この辺は使う人によってカスタマイズする部分だと思います。また、origという拡張子は一般的すぎるので、複数人が携わる場合はもっと特徴的な拡張子を使用したほうが好ましいでしょう。ただしdistも既に使われていることが多いので好ましくありません。
(2010-3-4追記).origファイルだけ存在する場合にはtarコマンドからエラーメッセージが出ます。きちんとエラーメッセージをラップした方が美しいとは思いますが、どうせ誰でも好きなようにカスタマイズできるシェルスクリプトなので特に対応せずに放置しています。

ダウンロード filesetup-bkup.sh

 

setup-bkup.sh

#!/bin/sh
set -e
EXT=.orig
MYNAME=`basename "$0"`
SRCEDIR=$1
DESTDIR=$2
BASEDIR=`pwd`
mkdir -p "${DESTDIR}" || exit
cd "${SRCEDIR}" || exit
cd "${BASEDIR}"
(cd "${SRCEDIR}";find . -type f -name "*${EXT}")|while read i
do
	DIRNAME=`dirname "${i}"`
	BASENAME=`basename "${i}" ${EXT}`
	if [ -f "${DESTDIR}/${DIRNAME}/${BASENAME}" ]; then
		if (diff "${SRCEDIR}/${DIRNAME}/${BASENAME}${EXT}" \
			"${DESTDIR}/${DIRNAME}/${BASENAME}">/dev/null) then
			:
		else
			echo "Not overwritten: \"${DESTDIR}/${DIRNAME}/${BASENAME}\""
			continue
		fi
	fi
	(cd "${SRCEDIR}";tar cpf - "${DIRNAME}/${BASENAME}${EXT}")|\
	(cd "${DESTDIR}";tar xpf -)
	(cd "${SRCEDIR}";tar cpf - "${DIRNAME}/${BASENAME}")|\
	(cd "${DESTDIR}";tar xpf -)
done
if [ "${MYNAME}" != "setup-bkup.sh" ]; then exit;fi
cd "${DESTDIR}"
find . -type d|sort -r|while read i
do
	cd "${BASEDIR}"
	cd "${SRCEDIR}"
	DIRMODE=`stat -c %a "${i}"`
	DIRUSER=`stat -c %u "${i}"`
	DIRGROP=`stat -c %g "${i}"`
	DIRTIME=`stat -c %y "${i}"|cut -b1-4,6-7,9-10,12-13,15-19|sed 's/:/./'`
	cd "${BASEDIR}"
	cd "${DESTDIR}"
	chmod $DIRMODE "${i}"
	chown $DIRUSER "${i}"
	chgrp $DIRGROP "${i}"
	touch -t $DIRTIME "${i}"
done

mod-dirtime.sh(ディレクトリの更新時間を含まれるファイルに合わせる)

DVDに焼く前によく使います。

#!/bin/sh -e
BASEDIR=`pwd`
find . -type d|sort -r|while read i
do
	cd "${i}"
	latestfile=`/bin/ls -1Atr|tail -1`
	if [ -n "${latestfile}" ]; then
		echo "latestfile ${latestfile}"
	DIRTIME=`stat -c %y "${latestfile}"|cut -b1-4,6-7,9-10,12-13,15-19|sed 's/:/./'`
	else
		echo "Directory:${i} is empty. Aborted."
		exit 1
	fi
	cd "${BASEDIR}"
	touch -t $DIRTIME "${i}"
done

remove-empty-dir.sh(空ディレクトリを削除する)

#!/bin/sh
find . -type d|sort -r|while read i
do
	rmdir "${i}" 2>/dev/null
	if [ $? -eq 0 ]; then
		echo "${i}"
	fi
done

慣れるとこんな書き方をするでしょう。

#!/bin/sh
find . -type d|sort -r|while read i
do
(rmdir "${i}" 2>/dev/null) && echo "${i}"
done

find-empty-dir.sh(空ディレクトリを探す)

空ディレクトリを探すだけならこんな感じでしょうか。これじゃ重いですが
findに-emptyオプションというものがありました。

find . -type d -empty

で探し出せます。でも削除は-execオプションを使ってもうまくいかないと思いますので、remove-empty-dirの方法がいいと思います。下の階層の空ディレクトリを削除した為に新たに生まれた空ディレクトリも削除できますし

おまけコーナーおわり


少し長さのあるもの

最近自分が使わないものは省きました。

[tip] convert-favorites-to-bookmarks.html.sh(IEのお気に入りを更新時間を保ったままFirefoxのbookmarks.htmlに変換)

はっきり言ってFirefoxの「ブックマークの管理」って実用に耐えないと思います。それだけしか知らなければ「そんなものかな」って思うかもしれませんが、少なくともIEのお気に入りをエクスプローラを使って整理する場合と比べて、遥かに使いづらく、作業効率が著しく劣ると思います。私はブックマーク類は全てIEのお気に入り形式に変換して管理・整理する方法をお薦めします。

私はFirefoxのブックマークもIEのお気に入り(インターネットショートカットファイル)形式で管理しています。
この方式のメリットとして、(1)管理がし易い(エクスプローラが使える為)、(2)ブックマーク以外のファイル類も一緒に保存しておくことができる、の2点が挙げられます。
Firefoxのブックマーク形式のままですと、非常に大量なブックマークの管理は次第に困難になってくると思いますが、IEのお気に入り形式だと何千個あっても管理は十分可能ですし、grepも出来ます。そしてお気に入りフォルダには、txt、doc、ppt、pdf等、あらゆる形式のファイルを一緒に置いておけるので、自分専用の強力な情報保存庫として使用できます。ただし本ツールは拡張子urlのファイルだけを処理するので、作成されたブックマークファイルにはブックマーク以外の情報は載りません(もちろんFirefoxもブックマークファイルにブックマーク以外を載せることを許可していません)。他の種類のファイルはエクスプローラ等からアクセスすることになります。
RSS等で集めたURLの内、後でまた見たいと思ったURLをIEのお気に入り形式して保存しておくことにしています。そしてそれをこのツールで時系列(更新時間の降順)に並べてFirefoxで活用するのが私のやり方です。
FirefoxでIEのお気に入りを作成する方法としては、ロケーションバーの左のアイコンをドラッグアンドドロップする方法を通常は使っています。Windows上だとそれだけでいいのですが、Linux版のFirefoxだとurlファイルではなくdesktopファイルが作成されてしまうので簡単な変換をおこなう必要があります。Firefoxのbookmarks.htmlからまとめて変換する場合はこちらのツールを使用します。Firefox3以降でのbookmarks.htmlを使ったブックマーク管理に関してはこちらを参考にして下さい。

今はOS間でブックマークを同期する方法が様々用意されているので、こんなものは時代遅れかもしれません。

$ convert-favorites-to-bookmarks.html.sh "/Windows... .../Favorites" bookmarks.html

みたいな感じで使用します。引数をわかりやく表すと、

$ convert-favorites-to-bookmarks.html.sh [お気に入りフォルダ] [出力先ファイル名]

ということになります。
UNIX・Linux環境汎用だし、単体で使用できるので、cron登録しておいて誰かのお気に入りをLAN内のhttpdに常に反映しておく、みたいな用途に向いていると思います。
その誰かのマシンのレジストリの、

HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Favorites

の%USERPROFILE%\Favoritesには、sambaサーバのドライブ上に設けたお気に入りフォルダの場所を書き込んでおけばいいかと思います。
もしくは、WindowsとLinuxのデュアル(マルチ)ブートのマシンとかでも役立つと思います。

  • UTF-8環境専用です。つまり標準で、シェル上でファイル名がUTF-8で取り扱われている必要があります。しかしファイルシステム上のファイル名の文字コードは直接関係ありません。現行の殆どのLinux環境で、ファイルシステムが何であれ、そのまま使用できる筈です。
  • 作成されたファイル自体はFirefoxのbookmars.html互換です。Windows用のFirefoxでも問題なく使用できます。但し、作成処理に関しては前行の条件がありますので、Windows上(のCygwin環境,..etc)でおこなえるどうかはわかりません。
  • お気に入りフォルダはNTFS上でもFAT上でもLinux,UNIXのsambaサーバ上でもOKです。
  • 他のブックマーク変換ツールの仕様を全然知らないのですが、このスクリプトはお気に入りファイルの更新時間をブックマークのADD_DATEに書き込みます。このスクリプトの逆方向の変換が出来る、すぐ下のconvert-bookmarks.html-to-favorites.plはお気に入りファイルの更新時間をブックマークのADD_DATEに合わせるので、この二つのツールで相互に変換を繰り返しても更新時間が保たれるという仕様となっています。(2008-5-23までは)こっちの方の対応が出来ていませんでした。両ツールを使うと複数のbookmarks.htmlのマージも自在に可能です。
  • 私の好みでフォルダの並びは名前順です。IEのお気に入りフォルダに他からお気に入りをコピーした際の仕様に似ています。
  • 私の好みでブックマークの並びは更新時間の降順です。IEのお気に入りをどんどん追加していった際の仕様に似ています。
  • 私の好みでフォルダはブックマークよりも上に位置しています。これもIEのお気に入りフォルダに他からお気に入りをコピーした際の仕様に似ています。
  • FAVICONは無視します。あまり興味ないし、IEとFirefoxでFAVICONの管理方法が全く違っていて対応が大変だし、対応するとファイルが肥大化するし、どうせFirefoxのbookmarks.htmlとして使用した場合、一度アクセスすると自動的にFAVICONは復活するからです。
  • 作成したブックマークファイルをFirefox 3以降に取り込む際の注意点・手順についてはこちら(別のツールの補足説明文)を参照して下さい。

ダウンロード fileconvert-favorites-to-bookmarks.html.sh
(2008-5-22)Firefoxで作成した拡張子がURL(大文字)のインターネットショートカットファイルにも対応しました。

 
#!/bin/bash
count_hierar()
{
	local count=0
	local src=${1}
	local str=
	while [ "${src}" != "" ]
	do
	str=${src%%/*}
	src=${src#*/*}
	if [ "$str" == "${src}" ]; then
		echo  ${count}
		return
	fi
	count=$((count+1))
	done
}
mk_spaces()
{
	local count=${1}
	local spaces=""
	for ((k=0;k<$count;k++))
	do
	spaces=${spaces}"    "
	done
	echo "${spaces}"
}
list_onedir()
{
	local relative=${1}
	local addflg=false
	local dir=
	cd "${relative}"
	[ "${relative}" == "." ] && relative=""
	if [ ${#relative} -gt 0 ]; then
		addflg=true
		WD="${WD}/${relative}"
	fi
	[ "${WD}" != "." ] && echo "${WD}">>${TMPFILE}
	find . -maxdepth 1 ! -name "." -type d|sort|while read i
	do
		dir=${i#*/}
		list_onedir "${dir}"
	done
	ls -tr ./*.{url,URL} 2>/dev/null|while read i
	do
		fname=${i#*/}
		echo "${WD}/${fname}">>${TMPFILE}
	done
	cd ..
	$addflg && WD=${WD%*/*}
}
analize_structure()
{
	local str=${befdirpath}
	local shallowcnt=0
	for ((j=$befhierarcnt;j>$hierarcnt;j--))
	do
		shallowcnt=$((shallowcnt+1))
		str=${str%*/*}
	done
	if [ "${str}" != "${dirpath}" ]; then
		shallowcnt=$((shallowcnt+1))
	fi
	echo ${shallowcnt}
	return
}
exitproc()
{ rm -f ${TMPFILE}; }
trap '
exitproc
exit 1
' 2 15
[ $# -lt 2 ] && echo "$0 favorites-dir bookmarks-file" && exit 1
BASEDIR=${1}
DESTFILE=${2}
hierarcnt=0
dirpath="."
spaces=""
[ "$(echo "${DESTFILE}"|cut -b 1)" != "/" ] && DESTFILE=$(pwd)/${DESTFILE}
cd "${BASEDIR}" 2>/dev/null
if [ $? -ne 0 ]; then echo "Can't move to ${BASEDIR}";exit 1;fi
BASEDIR=$(pwd)
TMPFILE=$(mktemp)
WD="."
list_onedir "."
cd "${BASEDIR}"
cat>"${DESTFILE}"<<EOT
<!DOCTYPE NETSCAPE-Bookmark-file-1>
<!-- This is an automatically generated file.
     It will be read and overwritten.
     DO NOT EDIT! -->
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<TITLE>Bookmarks</TITLE>
<H1>Bookmarks</H1>
<DL><p>
EOT
while read i
do
modifytime=$(stat -c %y "${i}"|sed 's/\-/\//g'|cut -b1-19)
adddate=$(date -d "${modifytime}" +%s)
befhierarcnt=${hierarcnt}
befdirpath=${dirpath}
fname=${i##*/}
[ -d "${i}" ] && i=${i}/
dirpath=${i%*/*}
hierarcnt=$(count_hierar "${dirpath}X")
if [ ${hierarcnt} -le ${befhierarcnt} -a "${dirpath}" != "${befdirpath}" ]; then
	shallowcnt=$(analize_structure)
	for ((j=$befhierarcnt;j>$(($befhierarcnt - $shallowcnt));j--))
	do
		spaces=$(mk_spaces $j)
		echo "${spaces}</DL><p>">>"${DESTFILE}"
	done
fi
spaces=$(mk_spaces $hierarcnt)
if [ -d "${i}" ]; then
	basename=${fname}
	cat>>"${DESTFILE}"<<EOT
${spaces}<DT><H3 ADD_DATE="${adddate}">${basename}</H3>
${spaces}<DL><p>
EOT
else
	basename=${fname%*\.url}
	basename=${basename%*\.URL}
	URL=$(grep "^URL"<"${i}"|cut -b 5-|sed 's/\n$//'|sed 's/\r$//')
	echo -n "    ${spaces}<DT><A ">>"${DESTFILE}"
	echo -n "HREF=\"${URL}\" ADD_DATE=">>"${DESTFILE}"
	echo "\"${adddate}\">${basename}</A>">>"${DESTFILE}"
fi
done<${TMPFILE}
echo "</DL><p>">>"${DESTFILE}"
exitproc

本来は1行で記述するところをecho -nで3行に分割したのは、wikiwiki.jpの制限を回避する為です。

[tip] convert-desktop-to-favorites.sh(Linux版等のFirefoxのロケーションバー左のアイコンをドラッグ&ドロップして作成したURLリンク(desktop)ファイルを、Windows用のインターネットショートカット(IEのお気に入り)に更新時間を保ったまま変換)

このスクリプトをGnome上のランチャーに登録しておくと、

utlshell_3_s.jpg

変換されて作成されたURLファイル(インターネットショートカットファイル)は完全にWindows互換です。
Gnomeデスクトップ上のファイルのみを対象としています。
※:上の説明でのURLファイルのアイコンは私の環境独自にカストマイズしたものです。この変更は簡単です。たとえばLinux Mint 13 MATEの場合、~/.icons/hicolor/48x48/mimetypes/application-x-mswinurl.pngという名前で好きな画像(アイコン)ファイルを置くだけです。(2009-11-20現在)Ubuntu9.10(デフォルトアイコンテーマはHumanity)では、アイコンをカスタマイズしてもファイルブラウザ上には反映されるものの、デスクトップ上には反映されないというバグがあるようです。(2010-5-4現在)Ubuntu 10.04でも9.10と同じ状態です。

 

※:私が使っているランチャー(gnomeのカスタム・アプリケーションのランチャ)の中身はこんな感じです。(2009-11-20現在)Ubuntu9.10では、ロケーションバー左のアイコンをドラッグ&ドロップしてURLリンク(desktop)ファイルを作成する機能にバグがあるようです。(2010-2-6追記)2009年12月頃には修正されていたと思います。
[~/.gnome2/panel2.d/default/launchers/convert-desktop-to-favorites.sh.desktop]

#!/usr/bin/env xdg-open
[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Terminal=false
Icon[ja_JP]=/usr/share/icons/gnome/48x48/filesystems/gnome-fs-bookmark.png
Name[ja_JP]=お気に入りに変換
Exec=/home/disklessfun/bin/convert-desktop-to-favorites.sh
Name=お気に入りに変換
Icon=/usr/share/icons/gnome/48x48/filesystems/gnome-fs-bookmark.png
 

ダウンロード fileconvert-desktop-to-favorites.sh

 

上のリンクからダウンロードして使用して下さい。一部wikiwiki.jpでは載せられない文字を含んでいる為、下をコピペして保存してもうまく動きません。
ファイル名変換の仕様は好きなように変更すればいいと思います。Windows上では使用できる文字が少ないのでそれに合わせる為の変換機能を持つ必要があります。なお、ダウンロードしたファイルをそのまま使用してもWindows版のFirefoxを用いた場合よりWindows互換性の高いURLファイルを生成します。
(2009-02-17)ファイル名変更の機能を6ケース(6行)追加しました。今までの仕様でもLinux上で使用する限りは問題なかったのですが、Windows上ではまだ問題がありました。Windows上での適応度の確認にはUnDupというソフトで読めるか否かで判定しています。
(2009-3-12追記)掲載の状態ではIEの仕様に合わせてあり、出力するURLファイルには「[Default]セクション」も出力します。しかしFirefoxのアドレスバーのアイコンをドラッグ&ドロップして作成したURLファイルには「[Default]セクション」はなく「[InternetShortcut]セクション」だけです。したがってWindows上でも主にFirefoxを使用している方は、スクリプト中の[Default]セクション」を出力する部分の2行をコメントアウトしてFirefoxの仕様に合わせた方が、重複もしくは差分チェックが有効に働く等の面から適切ではないかと思います。

#!/bin/bash
EXT=desktop
DESKTOP1=/home/${USER}/Desktop
DESKTOP2=/home/${USER}/デスクトップ
cd "${DESKTOP1}" 2>/dev/null||cd "${DESKTOP2}"||exit
ls ./*.${EXT} 2>/dev/null|while read -r i;do grep -q "^Type=Link$" "${i}" && echo "${i}" \
|while read -r i
do
URLLINE=$(grep "^URL=" "${i}")
modifytime=$(stat -c %y "${i}"|cut -b1-4,6-7,9-10,12-13,15-19|sed 's/:/./')
fname=${i#*/}
fname=${fname%*$EXT}URL
fname=$(echo "${fname}"|sed -e 's/~/~/'g)
fname=$(echo "${fname}"|sed -e 's/&#187;/-/'g)
fname=$(echo "${fname}"|sed -e 's/"/”/'g)
fname=$(echo "${fname}"|sed -e 's/\\///'g)
fname=$(echo "${fname}"|sed -e 's/?/?/'g)
fname=$(echo "${fname}"|sed -e 's/</</'g)
fname=$(echo "${fname}"|sed -e 's/>/>/'g)
fname=$(echo "${fname}"|sed -e 's/:/:/'g)
fname=$(echo "${fname}"|sed -e 's/;/;/'g)
fname=$(echo "${fname}"|sed -e 's/|/|/'g)
fname=$(echo "${fname}"|sed -e 's/,/,/'g)
fname=$(echo "${fname}"|sed -e 's/*/-/'g)
fname=$(echo "${fname}"|sed -e 's/\^/-/'g)
fname=$(echo "${fname}"|sed -e 's/&#160;/ /'g)
fname=$(echo "${fname}"|sed -e 's/―/―/'g)
fname=$(echo "${fname}"|sed -e 's/-/-/'g)
fname=$(echo "${fname}"|sed -e 's/&#234;/e/'g)
fname=$(echo "${fname}"|sed -e 's/&#243;/o/'g)
fname=$(echo "${fname}"|sed -e 's/@/@/'g)
while [ "$(echo "${fname}"|cut -b1)" == "-" ]
do
fname=$(echo "${fname}"|sed -e 's/^-//')
done
grep "^${URLLINE}.$" "${fname}" 2>/dev/null
if [ $? -ne 0 ]; then
echo -e "[Default]\r">"${fname}"
echo -e "BASE${URLLINE}\r">>"${fname}"
echo -e "[InternetShortcut]\r">>"${fname}"
echo -e "${URLLINE}\r">>"${fname}"
touch -t ${modifytime} "${fname}"
fi
rm "${i}"
done;done

convert-bookmarks.html-to-favorites.pl(Firefoxブックマークを更新時間を保ったままWindowsのインターネットショートカット(IEのお気に入り)に変換)

この項だけはPerlスクリプトです。

FirefoxのブックマークはWindowsとLinuxで共用できます。

私自身は最近はこのツールを使う機会が激減しました。WindowsでもメインのブラウザとしてFirefoxを使用しているのですが、最近はLinuxでも標準でNTFSを読み書きできるようになったので、WindowsのFirefoxで使っているブックマークをLinux側からも読み書きすることでブックマークの共用を実現しているからです。その共用に使う"ブックマーク"の具体的なファイル名はFirefox3以降ではplaces.sqliteです。Firefox3移行後しばらくはbookmarks.htmlを使って共用を実現していましたが、無理があるので現在は素直にplaces.sqliteで共用をおこなっています。Windows側、Linux側双方にProfileディレクトリがありますが、Windows側のplaces.sqliteにLinux側からシンボリックリンクを張って共用しています。
ところでここで触れたように、私は新しく作成したbookmarks.htmlを頻繁にFirefoxにインポートします。Firefoxの既存ブックマークにマージするのではなく、ブックマークをそっくり入れ替えます。この作業が簡単におこなえるように、大したことではありませんが私のFirefoxは少しだけカストマイズしてあります。以下に説明します。
Firefox3は起動時にブックマークを(1)places.sqllite、(2)bookmarkbackupsの中のバックアップ、(3)bookmarks.htmlの順番に探します。
(3)のbookmarks.htmlを読み込ませたい時に(1)のplaces.sqliteだけを削除すれば済むように、普段から(2)のbookmarksbackupsの中にバックアップを出力しない設定にしてあります。
browser.bookmarks.max_backupsを0です。
また、これはあまり必要なわけではないのですが、Firefox終了時にbookmarks.htmlを出力するように
browser.bookmarks.autoExportHTMLをtrueにしてあります。

シェルスクリプトbmc.shとPerlスクリプトbmc.plとのペアで使用します。
Firefoxやmozillaのブックマークを、階層構造を保ったまま、Windowsで用いられるurlファイル(インターネットショートカットファイル)に変換します。

 

私はブックマーク(アドレス)と関連するファイルを一緒に管理したいので、ブックマークは全て、アドレス1個毎にファイルがバラバラに作成されるurlファイル(Internet Explorerのお気に入り形式)に変換して管理しています。(この管理の仕方を補助するものがこれです。)

 

ブックマークを変換するソフトはWindows用のものはありますが、UNIX用の物はなかったと思うので、これはとても役に立っています。

 

ここ(本日のhoge(2003-11-07))から入手したPerlスクリプトを活用して簡単に作成しました。
(著作権を主張されていないので、私がその派生物をここで発表しても良さそうです。もちろん私もbmc.plに著作権を主張しません。)(2006-8-25:元にしたPerlスクリプトの作者様に基本的に自由に使用して良いとのお答えを頂きました。)
このPerlスクリプトの、bookmarks.htmlの階層構造を解釈する部分を参考にして作成したのがbmc.plです。自分自身ではbookmarks.html解析の努力を全く払っていません。

 

シェルスクリプト+Perlスクリプト(ZIP圧縮) 2008-5-23 更新
utf-8環境用となっています。
2006-9-5 firefox 1.5系でのシングルクォートの取扱仕様変更に対応しました。
(2007-7-9) urlファイルの更新時間をfirefox上でそのブックマークを追加した時間に一致させる機能を追加しました。これは以前からおまけで公開していた版とは異なります。
シェルスクリプトでファイルの更新時間を操作するサンプルとしては、これとかこれがあります。どちらもls --full-timeではなくstatを使っています。この項のものは、Perlを使っています。wavedash(~、いわゆる、にょろ)の処理もおこなっています。
(2008-5-23)上のconvert-favorites-to-bookmarks.html.shで作成した直後の「ADD_DATEと>が続いているファイル」を処理できませんでしたが、対応しました。
BookMarkConverter.zip (2008-11-22)ダウンロード(BookMarkConverter)停止

 

ダウンロード fileconvert-bookmarks.html-to-favorites.pl
(2009-02-17)convert-desktop-to-favorites.plと同様の変更を加えました。
(2008-12-15)正しいファイルに差し替え。
(2008-11-22)単一Perlスクリプトに変更してダウンロード開始。

 
$ convert-bookmarks.html-to-favorites.pl  firefox-setting-dir/bookmarks.html destination-dir

みたいな感じで使用します。destination-dir下に階層構造まで含めて変換されます。
従来のBookMarkconverter.zipに含まれていたbmc.plに7行追加しただけのものです。
ていうか、最初から単一のPerlスクリプト形式でも良かったんですが、シェルスクリプトのページに載せるために無理やり呼び出し用のシェルスクリプトを使用していたというのが実情です。
(2009-3-12追記)掲載の状態ではIEの仕様に合わせてあり、出力するURLファイルには「[Default]セクション」も出力します。しかしFirefoxのアドレスバーのアイコンをドラッグ&ドロップして作成したURLファイルには「[Default]セクション」はなく「[InternetShortcut]セクション」だけです。したがってWindows上でも主にFirefoxを使用している方は、スクリプト中の[Default]セクション」を出力する部分の2行をコメントアウトしてFirefoxの仕様に合わせた方が、重複もしくは差分チェックが有効に働く等の面から、適切ではないかと思います。

[tip] isoplay.sh(DVDビデオをリップしたisoファイルをダブルクリックするだけで再生する)

(2008-12-6)失礼しました。VLCとかxineは直接isoファイルを読み込む機能を持っていたんですね。ワンライナーで済む問題でした。
DVD視聴ソフトとしては使い方に慣れが必要ですが、好みでVLCを呼び出しています。VLCの設定でDeinterlaceをデフォルトにしておけば、ファイルブラウザ(Nautilus)上でisoファイルをダブルクリックするだけでDVDが次々と視聴できます。
[isoplay.sh]

exec vlc dvd:///"$1"

実際にはファイルブラウザ上でisoファイルの開き方として「vlc dvd:///%f」か「xine dvd:///%f」を登録すれば済みます。

locate-i(簡単に大文字小文字の区別なくファイルを探し出すために作成したlocateコマンドのラッパースクリプト)

locateコマンドに、grepコマンドのiオプション、findのinameオプションに相当する機能を追加します。
locateコマンドについては以下のリンクを参照して下さい。

例えば

$ locate-i "personal toolbar folder"

で、ファイル名の一部に次のどの文字列が含まれていても全て探し出すことができます。
Personal Toolbar Folder
PeRSOnaL toOLBaR fOLDeR
PERSONAL TOOLBAR FOLDER

(2010-3-22)dashでエラーが出力されないように修正しました。

#!/bin/sh
[ $# -lt 1 ] && exit
src=$1
lowstr=`echo "$src"|tr \'[A-Z]\' \'[a-z]\'`
cnt=`echo "$lowstr"|awk 'BEGIN {FS="\n"};{print length($1)}'`
while [ "$cnt" -gt 0 ]
do
low=`echo "$lowstr"|awk 'BEGIN {FS="\n"};{print substr($1,1,1)}'`
lowstr=`echo "$lowstr"|awk 'BEGIN {FS="\n"};{print substr($1,2)}'`
upp=`echo $low|tr \'[a-z]\' \'[A-Z]\'`
if [ "$low" = "$upp" -o "$low" = " " ]; then
        str=$str$low
else
        str=$str[$low$upp]
fi
cnt=`expr $cnt - 1`
done
locate "*$str*"

dpkg-qf(dpkg -Sをrpm -qf風にするラッパースクリプト)

(2009-3-31追記)dpkg-query -Sがありました。あるんじゃないかなあ?と思いながらも自前で作成したのでした。以下の説明にあるように少し仕様が違います。
rpm系を経験してからdeb系に移るとdpkg -Sの出力は不便だと感じると思います。
試しにdpkg -S ftpやdpkg -S wを試みてみて下さい。出力が多すぎて何がなんだかわかりませんよね。
このスクリプトを使用するとこんな感じになります。

$ dpkg-qf /usr/bin/ftp
ftp: /usr/bin/netkit-ftp
$ dpkg-qf /usr/bin/w
procps: /usr/bin/w.procps

一目でどのパッケージに属しているか、そして実体ファイルが何なのかがわかるようになります。

このスクリプトは本家rpm -qf(およびdpkg-query -S)とは異なり、指定されたファイルがシンボリックファイルである場合には実ファイルまで辿る仕様となっています。なので、自分で独自に作成したシンボリックリンクを引数に指定した場合でもそのコマンドの実体ファイルがどのパッケージに属しているかを表示することができます。たとえば先ほどのwを例にとると、

$ ln -s ../../../usr/bin/w /home/disklessfun/bin/my-command
$ dpkg-qf /home/disklessfun/bin/my-command
procps: /usr/bin/w.procps

となります。
これを開発したりカストマイズする際なんかにはとても役立ちます。

[dpkg-qf]

#!/bin/bash -e
test $# -lt 1 && echo "eg. $0 fullpath" && exit 1
seekfile()
{
local fpath=$1
local dirpath line sympath
while test -L "${fpath}"
do
dirpath=${fpath%*/*}/
line="$(stat "${fpath}"|grep "File: ")"
line="${line##*\`}"
line="${line%*\'*}"
if test "${line:0:1}" != "/"; then
fpath="${dirpath}${line}"
else
fpath="${line}"
dirpath=/
fi
done
echo "${fpath}"
}
test "${1:0:1}" != "/" && echo "$1 must be a full path" && exit 1
fullpath=${1}
fullpath=$(seekfile "${fullpath}")
filename=${fullpath##*/}
dpkg -S "${filename}"|grep "${fullpath}$"

dircp.sh(ディレクトリだけを、ディレクトリ構造,owner,group,更新時間を保ったままコピーする)

このスクリプトをデモってみます。

# mkdir /work
# cd /work
# dircp.sh ../var var

この操作で/var以下のディレクトリのみのコピーが/work/の中に作成されます。
既にコピーを作成した後に再度実行した場合は、コピー元とコピー先のディレクトリのプロパティを合わせる動作だけをおこないます。不要ファイルを削除した際にディレクトリのプロパティが変化することを避けたい場合に役立てると思います。
あまり需要はないと思いますが一応公開しておきます。Java開発者の方とかには役に立つかもしれません。
ソースをあまり読まない人用に補足説明をしておきます。
このスクリプトの働き自体は「(cd "$1";find . -type d|cpio -o)|(mkdir -p "$2";cd "$2";cpio -idm)」と同じです。(「find "$1" -type d|cpio -pdm "$2"」だと思う人もいると思いますが、少し違います。)
このスクリプトはもっと複雑なコピーや加工をおこなうスクリプトのベースとして掲載しています。(このスクリプトの起源は全く異なる用途でした。)サンプルとしては少し複雑すぎる実際の応用編がこれです。
(2007-7-8) 下側のループでmkdir -pすれば上側のループは必要ありません。しかし、それだと処理的に汚いと思うので上側のループを設けています。まあ、お好みの範囲です。上側のループの -pは再度実行した際にエラーを出さないことを意図しています。

#!/bin/sh
set -e
SRCEDIR=$1
DESTDIR=$2
BASEDIR=`pwd`
mkdir -p "${DESTDIR}" || exit
cd "${SRCEDIR}" || exit
find . -type d|while read i
do
	cd "${BASEDIR}"
	cd "${DESTDIR}"
	mkdir -p "${i}"
done
cd "${BASEDIR}"
cd "${SRCEDIR}"
find . -type d|sort -r|while read i
do
	cd "${BASEDIR}"
	cd "${SRCEDIR}"
	DIRMODE=`stat -c %a "${i}"`
	DIRUSER=`stat -c %u "${i}"`
	DIRGROP=`stat -c %g "${i}"`
	DIRTIME=`stat -c %y "${i}"|cut -b1-4,6-7,9-10,12-13,15-19|sed 's/:/./'`
	cd "${BASEDIR}"
	cd "${DESTDIR}"
	chmod $DIRMODE "${i}"
	chown $DIRUSER "${i}"
	chgrp $DIRGROP "${i}"
	touch -t $DIRTIME "${i}"
done

ntfsdirs-time-copy.sh(フォルダの更新時間をコピーする)

上と中身が殆ど同じで冗長になってしまうのですが、成り行き上掲載します。
Windowsのエクスプローラでフォルダをコピーまたは移動するとコピー先または移動先のフォルダの更新時間は元と異なった値になってしまいます。これが気にいらない人はrobocopyを使うらしいのですが、私はエクスプローラでコピーした後、下の内容のシェルスクリプトを使って"更新時間だけ"をコピーします。
ファイル名にntfsと付いていますが、実際にはFAT,FAT32でもext3でも使用できます。
[ntfsdirs-time-copy.sh]

#!/bin/sh
if test $# -lt 2; then
echo "eg. $0  Source-dir Destination-dir"
exit
fi
SRCEDIR=$1
DESTDIR=$2
BASEDIR=`pwd`
cd "${SRCEDIR}" || exit
cd "${BASEDIR}"
cd "${DESTDIR}" || exit
find . -type d|sort -r|while read i
do
case $i in
./RECYCLER/*|./Recycled/*|./System\ Volume\ Information/*)
;;
*)
	cd "${BASEDIR}"
	cd "${SRCEDIR}"
	DIRTIME=`stat -c %y "${i}"|cut -b1-4,6-7,9-10,12-13,15-19|sed 's/:/./'`
	cd "${BASEDIR}"
	cd "${DESTDIR}"
	echo "${i}"
	touch -c -t $DIRTIME "${i}"
;;
esac
done

gen-splitted-isoimage.sh(1層に収まらないDVDISOイメージを2分割したISOイメージを作成する)

レンタルした2層DVDを1層化して手元に残すというのはよくある手ですが、出来ることなら元の画質のままで残したいものです。かといって、いくら大容量ハードディスクが安くなったとはいえ、滅多に見る予定のないDVDを長期間ハードディスクに残しておきたくもありません。そこで私がよくやるのはDVDISOイメージをバイナリで2分割して2枚の片面DVD-(+)Rに焼くという手法です※。
ここによると、この行為は現在の著作権法に違反していないそうです。(2012-6-21追記)2012年10月1日以降は違法となります。
(2009-9-15)小改造を加えまして、isoファイルだけでなく、あらゆる種類のファイルあらゆる拡張子のファイルに標準対応しました。isoファイル以外でもスクリプトを修正せずにそのまま処理できます。

 

ヘッダ部のコメントにありますが、このスクリプトを動作させる為にはいくつかのコマンドをパスワードなしでsudoできるように/etc/sudoersの末尾に追記しておく必要があります。ヘッダ部にある設定は最小限の設定です。既にあらゆるコマンドをパスワードなしでsudoできるように設定済み等の場合は新たに設定する必要はありません。
このスクリプトは私が長らく手動でおこなってきた操作と全く同じ仕様にしています。

  • カレントディレクトリに分割DVDISOファイルを作成。作業ディレクトリもカレントディレクトリ直下に作成。実行前の時点でカレントディレクトリには元DVDISOの1.5倍の空き容量が必要
  • 分割DVDのボリュームラベルは1枚目が元(iso9660)ボリュームラベル_1、2枚目が元ボリュームラベル_2
  • それぞれのDVDにWindows用のエクスプローラを開くautorun.infを同梱
  • 2枚目に元DVDISOのmd5ハッシュ値を保存(md5sum.txt)。中の記述のDVDISOファイル名はUTF-8
  • 2枚目にWindows用の連結バッチファイルを同梱
  • 元DVDISOの拡張子はISOもしくはisoに対応(とはいってもこのスクリプトは物理的に2分割するだけなので対応拡張子を変更するだけで事実上どのような種類のファイルも分割可能です)←(2009-9-15追記)当初仕様ではisoファイル以外を処理する場合はスクリプトを少し修正する必要がありましたが、現仕様ではその必要はありません。
  • スクリプトの最後でベリファイチェックをおこなう
  • iso以外のファイルを処理した場合、分割DVDのボリュームラベルは1枚目がSPLITTED_1、2枚目がSPLITTED_2

バッチファイルを同梱していますが、私自身がそれを使うことは今後もまずないと思います。Linux上で1枚目に入っている前半部をハードディスクにコピーし、2枚目に入っている後半部を前半部の後ろにcatした方が簡単だし速いからです。
最後のベリファイチェックはハードディスクに障害でもない限り、まず普通は必要ありません。なので途中で[Ctrl]+[C]してもいいようになっています。作業ディレクトリ(分割DVDのボリュームラベル名のディレクトリ)が削除されていれば分割ISOファイルの作成は既に終わっています。
いつものように説明代わりにset +xして経過を目に見えるようにしています。
スクリプト中で使用しているmkisofsですが、私は本物のmkisofsコマンドを使用しています。Winsows 2000でも読めるようにUDF1.5で作成する為です。最近のディストリビューションの標準では/usr/bin/mkisofsはmkisofsの後継的存在であるgenisoimageへのシンボリックリンクになっていますが私はそのシンボリックリンクを削除して手動でmkisofsをインストールしています。(2010-3-14追記)最近のgenisoimageは互換性の問題が解消したような気がします。
(2010-2-6追記)ここにも書きましたが、LinuxでのNTFSへの書き込み機能は安全ですが、不完全なものです。作業ディレクトリ(=カレントディレクトリ)がNTFSの場合、フラグメントが進んでいて且つ空き容量に余裕が少ない場合には処理が途中でストップする場合がありえます。このことは一応頭のどこかに留めておいて下さい。
(2010-2-10追記)losetupコマンドにfオプションがない、古い環境でも使えるように修正しました。あと、前半で[Ctrl]+[C]した場合にも作業ディレクトリを消すようにしました。←今までは処理内容をゆっくり観察できるようにわざと残してありましたが…
(2010-3-14追記)先月の更新内容にバグがありました。本日その修正版をアップしました(自分専用のmkisofsのチェック箇所も紛れ込んでいたので一緒に削除しました)。前回の版では完全に勘違いをしていて使ってはいけない箇所でtrを使用していました。本日、前回の更新以来始めて本スクリプトを使用して気づきました。前回のバグ入の版は10人程度の方がダウンロードされたようですが、バグの害について説明しておきます。このバグはいつも害を及ぼすとは限らず、mktempで作成したテンポラリーファイルに数字が含まれていた場合のみ出現します。で具体的な内容ですが、たとえば分割対象のisoファイルのボリュームラベルがTHIS_IS_ITなら仕様上は分割isoのボリュームラベルはTHIS_IS_IT_1とTHIS_IS_IT_2にならなければならない筈ですが、バグが現れた場合にはDVD_ISO_1とDVD_ISO_2になります。もちろん連結してisoを再作成すればそのボリュームラベルはちゃんとTHIS_IS_ITになりますから、気にするほどの害はなかったとも言えます。
(2015-1-5追記)新しい環境で使用したところ、引数なしでmountコマンドを実行した際の仕様が変更されていて、またDVD_ISO_1、…になってしまっていました。使用コマンド数を減らそうとlosetupの使用を控えたことがあだになりました。素直にlosetupコマンドを使用する仕様に変更して対応しました。
(2015-1-12追記)。losetup使用に従って丸々ソースファイル名で検索する必要が生じました。[]を含むファイル名に対応する為エスケイプ処理を加えました。また2x4.7GBサイズに対応する為allow-limited-size指定を追加しました(もう互換性の問題を心配する必要はほぼありません)。あと私の環境のgenisoimageのバグなのか?ボリュームラベル長が30バイト以上だとラベル末尾が文字化けするので29バイト以内に切り詰めるようにしました。
ダウンロード filegen-splitted-isoimage.sh 2015-1-12更新
ソースファイル名が128文字を超えてないかのチェックにはこのスクリプトの64を128に変更したものを使って下さい。
(2015-10-29追記)最近はBDの方がDVDよりもはるかに容量当たりの単価が安いので本スクリプトの出番も少ないかもしれません。ただしもちろん本スクリプトは、BD一層に入りきらない巨大サイズのファイルを分割する用途にも使えます。

 

[gen-splitted-isoimage.sh]

#!/bin/bash -ex
# Needed settings in /etc/sudoers.
#disklessfun	ALL=(ALL) NOPASSWD: /usr/bin/volname
#disklessfun	ALL=(ALL) NOPASSWD: /bin/mount
#disklessfun	ALL=(ALL) NOPASSWD: /bin/umount
gen-autorun-inf()
{
local dirpath=${1}
echo -e "[autorun]\r">"${dirpath}/autorun.inf"
echo -e 'open=explorer.exe /n,\\'"\r">>"${dirpath}/autorun.inf"
}
escapepattn()
{
local pattn=${1}
pattn="`echo "${pattn}"|sed -e 's/\[/\\\[/'g`"
pattn="`echo "${pattn}"|sed -e 's/\]/\\\]/'g`"
escapedmatchpattn=${pattn}
}
escapedmatchpattn=
test $# -lt 1 && echo "eg. $0 hoge.iso[img,dmp,tgz, etc]" && exit 1
SRCFILE=$1
filename=${SRCFILE##*/}
ext=${filename##*\.}
test "${ext}" = "${filename}" && echo "Extension not found" && exit 1
basename=${filename%*\.$ext}
dirname=${SRCFILE%*/*}
test "${dirname}" = "${filename}" && dirname=.
MNTDIR=$(mktemp -d)
set +e
sudo mount -o ro,loop "${SRCFILE}" ${MNTDIR}
RET=$?
set -e
if [ $RET -eq 0 ]; then
escapepattn "${SRCFILE}"
LODEV=$(losetup -a|grep "${escapedmatchpattn}"|cut -d":" -f1|tail -1)
#VOLNAME="$(sudo volname ${LODEV}|tr -cd '0-9A-Z_')"
VOLNAME="$(sudo volname ${LODEV}|tr -d '\040')"
sudo umount ${MNTDIR}
else
VOLNAME=SPLITTED
fi
rmdir ${MNTDIR}
test -z "${VOLNAME}" && VOLNAME=DVD_VIDEO
vollength=${#VOLNAME}
#test ${vollength} -gt 30 && VOLNAME=${VOLNAME:0:30}
test ${vollength} -gt 27 && VOLNAME=${VOLNAME:0:27}
filesize=$(stat -c %s "${SRCFILE}")
filesizeM=$(($filesize / 1048576))
halfsizeM=$(($filesizeM / 2))
exitproc1()
{
rm -rf "${VOLNAME}_1" "${VOLNAME}_2"
}
trap '
exitproc1
exit 1
' 2 15
mkdir "${VOLNAME}_1" "${VOLNAME}_2"
gen-autorun-inf "${VOLNAME}_1"
gen-autorun-inf "${VOLNAME}_2"
set +x
basenames="$(echo "${basename}"|iconv -f UTF-8 -t CP932)"
echo -n "COPY /B \"${basenames}.000\"+\"${basenames}.001\" \"${basenames}.$ext\ ""> \
"${VOLNAME}_2/${basename}.bat"
set -x
echo -e "\r">>"${VOLNAME}_2/${basename}.bat"
WD=$(pwd)
/bin/bash -ex -c "cd "${dirname}";md5sum \"${filename}\" > \
"${WD}/${VOLNAME}_2/md5sum.txt""
dd if="${SRCFILE}" bs=1M count=$halfsizeM of="${VOLNAME}_1/${basename}.000"
#mkisofs -V "${VOLNAME}_1" -udf -r -o "${VOLNAME}_1.iso" "${VOLNAME}_1"
genisoimage -V "${VOLNAME}_1" -allow-limited-size -r -o "${VOLNAME}_1.iso" "${V OLNAME}_1"
rm -rf "${VOLNAME}_1"
dd if="${SRCFILE}" bs=1M skip=$halfsizeM of="${VOLNAME}_2/${basename}.001"
#mkisofs -V "${VOLNAME}_2" -udf -r -o "${VOLNAME}_2.iso" "${VOLNAME}_2"
genisoimage -V "${VOLNAME}_2" -allow-limited-size -r -o "${VOLNAME}_2.iso" "${V OLNAME}_2"
orghash="$(cat "${VOLNAME}_2/md5sum.txt")"
rm -rf "${VOLNAME}_2"
exitproc2()
{
sudo umount "${MNTDIR1}"
sudo umount "${MNTDIR2}"
rmdir ${MNTDIR1} ${MNTDIR2}
}
trap '
exitproc2
exit 1
' 2 15
MNTDIR1=$(mktemp -d)
MNTDIR2=$(mktemp -d)
sudo mount -o loop,ro "${VOLNAME}_1.iso" "${MNTDIR1}"
sudo mount -o loop,ro "${VOLNAME}_2.iso" "${MNTDIR2}"
newhash="$(cat "${MNTDIR1}/${basename}.000" "${MNTDIR2}/${basename}.001"|md5sum )"
set +x
echo;
echo "Original hash value."
echo "${orghash}";echo
echo "Archived hash value."
echo "${newhash}";echo
set -x
exitproc2
set +x
echo "Done."

chkjoliet.bash(ファイルツリーがJolietで焼くのに適しているかチェックする)

私はよくLinux上でLinux・Windows兼用DVDを焼きます。Joliet形式の場合(最近はその必要性はあまりないと思います。関連記事)、ディレクトリ名、ファイル名の長さが64文字以内という制限があります。それを満たしているかのチェックに使います。まあ実際は他の目的用のスクリプトのベースになるかなってところでしょうか。
Windows用にこんなソフトがありますが、そのシェルスクリプト版といったところでしょうか。ただしこちらに修正機能はありません。
※:最近のmkisofsには -joliet-long というオプションがあって、それを使うとJolietでも103文字まで許されるそうです。規格外なのですが使えるそうです。
bash完全限定です。zshやkshはマルチバイト文字の扱いが異なり、間違った結果が出力されてしまいます。

#!/bin/bash
find .|while read i
do
fname=${i##*/}
length=${#fname}
if [ ${length} -gt 64 ]; then
echo "${i#*/*} :${length}"
fi
done

dupchk.sh(ファイルツリーが大文字小文字の重複を許さないファイルシステムに適合しているかチェックする)

上のchkjoliet.bashと同じく、Linux・Windows兼用DVDを焼く前のチェックに使ったりします。
Linuxで作成したDVDの中身をWindows上で読み込んでハードディスクにコピーしている途中にフォルダ名やファイル名の重複エラーが発生してしまうことがあります。そんなことがないようにこのスクリプトでDVD作成前にチェックをおこないます。まあ余程まぎらわしいファイル名が多数ある場合以外は目視で事足りるわけですけど

#!/bin/sh
exitshori()
{ rm -f /tmp/dupchk*; }
trap '
exitshori
exit 1
' 2 15
tmpfile1=/tmp/dupchk.tmp
find . ! -name ".">$tmpfile1
cat $tmpfile1|sort -f -u |while read i
do
	hit=`grep -i "^$i$" $tmpfile1|wc -l`
	if [ $hit -ge 2 ]; then
		echo "hit $hit"
		echo "$i"
	fi
done
exitshori
exit 0

extract-backuped-pbr.sh(NTFSパーティションの最後尾に保存されているPBRのバックアップを取り出す)

本スクリプトはMicrosoft提供のツールとは違い、自動計算でブートセクタのバックアップを取り出すことができます。また、Windowsがブートしない状況でも、One CD Linux上で作業がおこなえます。


当初、ブートパーティションのみに使用可能と記していましたがデータ専用のパーティションでも使用できることがわかり、2008-2-1に修正しました。
当サイトでは以前からNTFSのPBRを完全に壊してしまった場合の私なりの修復法をこのページに載せているわけですが、このほど(2008-1-11)読者の方が当サイトの掲示板に「NTFSにはPBRのバックアップがパーティションの最後尾に保存されている」と書き込んで下さいました。このことを私も以前に見聞きしたような気がしますが、すっかり頭から消えていました。(Microsoftの資料) 早速、実際に確認作業をおこないました。バックアップのPBR(末尾のセクタ)を抽出するスクリプトを作成し、パーティションの末尾のセクタを先頭セクタ(PBR)に上書きコピーすることによっても、NTFSのPBRが修復出来ることをWindows XP,2000の環境で確認しました。

 

ダウンロード fileextract-backuped-pbr.sh   (2015-7-8更新)最近のfileコマンドに対応しました。最新のLinux環境でも最後の説明メッセージが出るようになりました。 (2010-5-15更新)(簡単に言うと)Windows 7に対応しました。従来のものはハードディスクの標準的な使い方をそのままプログラミングしたようなものだったんですが、その方法ではWindows 7が作成する環境でfdiskコマンドがうまく対応できないので、別の(もっとシンプルな)方法を使う内部仕様に変更しました。 (2008-12-28更新)ダブルクォートが抜けていて、厳密に言うと文法が間違っていた個所を修正しました。多分動きに違いはないと思います。 (2008-12-16更新)スクリプト内部で使用しているGNU fileコマンドの最近の仕様変更に対応しました。Ubuntu8.10への対応です。
旧(厳密には旧旧)版もダウンロードできるようにしておきます。ダウンロード fileold.extract-backuped-pbr.sh

 

ただし、このスクリプトは当該パーティションがシリンダ境界に沿って確保されている場合のみ正常に動作します。まあ殆どの環境ではパーティションはシリンダ境界に沿って確保されているので、多分、一応は殆どの環境に適合していると思います。参考(このページの補足)。(2010-5-15追記)現在の版はシリンダ境界に依存しません。

このスクリプトはLinux専用です。だからこそ、Windowsが起動しなくなった状態の復旧に向いているわけです。KNOPPIXやUbuntuライブCD上でも使用可能なので、わざわざLinuxをインストールする必要はありません。理想を言えば、ネットワーク上にこのようなものを仕込んだサーバを設置しておくと、障害復旧作業が非常に迅速におこなえると思います。

Linuxに詳しくない人のために簡単にTipsを書いておきます。まずrootユーザになるかsudoで fdisk -l を実行して下さい。Linuxでパーティションをどのように表記するかがわかります。もし、このときに当該パーティションについて「シリンダ境界に従っていない」等のメッセージが表示されれば、このスクリプトの実行に適していない環境だということになります。(ただしそのような環境は滅多にありません)

正常に処理が終了したら、カレントディレクトリにちょうど512バイトのファイルが作成される筈なのでそれによって成否の判別がおこなえます。読み出しサイズを指定(count指定)していないのに512バイトのファイルが作成されたということは「読み出し位置の指定が正しい」ことの証明になります。加えてスクリプト中では抽出したファイルがNTFSのブートセクタであるかのチェックもおこなっています。(NTFSのブートセクタでないと判明した場合もファイルは削除していません。また、基本領域・論理領域双方に対応しています。)
正常に処理が終了した場合は抽出したPBRイメージファイルを壊れたPBRに上書きする為のddコマンドの構文が出力されます。それに従って例えば次のようにddコマンドを実行すれば修復が完了します。

# dd if=backuped-sda1-pbr.img of=/dev/sda1

ソース (かなり簡単です)

#!/bin/bash -e
if [ $# -lt 1 ]; then
echo "eg. $0 /dev/sda1"
exit 1
fi
LANG=C
DEVICE=$1
common=${DEVICE%/*}
devname=${DEVICE##*/}
left3char=$(echo ${devname}|cut -b1-3)
devicenumber=$(echo ${devname}|cut -b4-)
DISK=${common}/${left3char}
echo "Target Disk :${DISK}"
echo "Target Partition :${DEVICE}"
outputfile=backuped-${devname}-pbr.img
firstsector=$(fdisk -lu ${DISK}|grep "${DEVICE} "|sed 's/\*//'|awk '{print $2}')
lastsector=$(fdisk -lu ${DISK}|grep "${DEVICE} "|sed 's/\*//'|awk '{print $3}')
fsid=$(fdisk -lu ${DISK}|grep "${DEVICE} "|sed 's/\*//'|awk '{print $5}')
if [ "${fsid}" != "7" ]; then
echo "Error, ${DEVICE}: Id is not 07"
exit 1
fi
echo "firstsector :${firstsector}"
echo "lastsector :${lastsector}"
sectors=$((${lastsector} - ${firstsector} +1))
echo "total sectors :${sectors}"
skipsectors=$((${sectors} -1))
echo "skipsectors :${skipsectors}"
echo
echo "Extracting backuped PBR..."
dd if=${DEVICE} of=${outputfile} bs=512 skip=${skipsectors} >/dev/null 2>&1
filesize=$(stat -c %s ${outputfile})
echo
if [ ${filesize} -eq 512 ]; then
if (file ${outputfile}|grep -q "NTFS") then
echo "Finished, ${outputfile} is here."
echo "You may execute \"dd if=${outputfile} of=${DEVICE}\""
elif (file ${outputfile}|grep -iq "x86 boot sector") then
if (strings ${outputfile}|grep -iq "NTLDR is missing") then
echo "Finished, ${outputfile} is here."
echo "You may execute \"dd if=${outputfile} of=${DEVICE}\""
fi
else
echo "Error, Not a NTFS boot sector"
exit 1
fi
else
echo "Error, filesize :${filesize}"
fi


(余談)
誤ってパーティションテーブルを壊してしまったときなどに「パーティションテーブルの修復」が出来れば便利です。以前からgpartという修復を助けるソフトウェアがあるにはありますが、完全なものとは言えません。もし私がパーティションテーブルの修復をする羽目になったら、そしてそのハードディスクがNTFSとFATだけで使用していたなら、私は自分でgpartの代わりにパーティションテーブルの修復を助けるシェルスクリプトを作ると思います。HSの値を仮定してやれば、PBRの位置は絞られますから、シェルスクリプトで十分に探索が可能です。(NTFSとFATのPBRは非常に特徴的ですから)拡張領域も含めて全てのパーティション情報を復元できると思います。
但し、私はそんな羽目にならないようにパーティションテーブルの情報は日頃から確実にバックアップをとっています。いつ何時マイナーなOSのインストーラがパーティションテーブルを壊すかもしれないと思うからでもあります。テキスト情報ですから場所も殆ど必要ありません。
※ (2008-12-16)試験的ににごく簡単な"パーティションテーブルを推量するシェルスクリプト"を作成しました。実際のパーティションテーブルの修正はおこなわないので修復スクリプトとは呼べません。あくまで推量スクリプトです。fdiskとの親和性の高い出力をおこないますので、gpartよりも役に立つこともあると思います。NTFS,FATおよびGRUBのブートセクタを検出することでパーティションテーブルの推量をおこないます。勘のいい人は気づいたかもしれませんが、2段階ブートに統一して、Linux OSのパーティションの先頭にGRUBをインストールしていると、パーティションテーブルの推量(および修復)に有利です。次にこのスクリプト(ツール)の制限を挙げます。gpartなんかと同様な制限なのですが、NTFS,FATおよびGRUBのブートセクタを見逃すことはないのですが、構成変更をおこなった経験のある古いハードディスクなんかだと過去に使われていたブートセクタを誤検出してしまうことがあります。ただしこれは当然仕方のないことです。(2008-12-30)本質的には何も進歩していないのですが、細々と変更をおこなっています。
(余談2)
このスクリプトではパーティションテーブルは参照するだけで更新はしないのでfdiskコマンドを使用しています。シェルスクリプトでパーティションテーブルを更新する場合にはsfdiskコマンドを使用します。
(おまけ)
上のスクリプトからechoとかFSIDのチェックを削除して、単純に指定パーティションの末尾のセクタを抽出する機能だけを持つスクリプト(もちろん上と同じく、シリンダ境界に沿って確保されているパーティションにのみ対応)(基本領域・論理領域双方に対応していますが、出力する意味のないIdが5とかfの領域を除外する処理は組み込んでいません)

#!/bin/bash -e
if [ $# -lt 1 ]; then
echo "eg. $0 /dev/sda1"
exit 1
fi
LANG=C
DEVICE=$1
common=${DEVICE%/*}
devname=${DEVICE##*/}
left3char=$(echo ${devname}|cut -b1-3)
devicenumber=$(echo ${devname}|cut -b4-)
DISK=${common}/${left3char}
outputfile=lastsector-${devname}.img
firstcylinder=$(fdisk -l ${DISK}|grep "${DEVICE} "|sed 's/\*//'|awk '{print $2}')
lastcylinder=$(fdisk -l ${DISK}|grep "${DEVICE} "|sed 's/\*//'|awk '{print $3}')
cylinders=$((${lastcylinder} - ${firstcylinder} + 1))
st=$(fdisk -l ${DISK}|grep "sectors/track"|awk '{print $3}')
sc=$(fdisk -l ${DISK}|grep "cylinders of"|awk '{print $5}')
if [ ${devicenumber} -le 4 ]; then
sectors=$((${cylinders} * ${sc}))
else
sectors=$((${cylinders} * ${sc} - ${st}))
fi
if [ ${firstcylinder} -eq 1 ]; then
sectors=$((${sectors} - ${st}))
fi
skipsectors=$((${sectors} -1))
dd if=${DEVICE} of=${outputfile} bs=512 skip=${skipsectors} >/dev/null 2>&1
filesize=$(stat -c %s ${outputfile})
if [ ${filesize} -eq 512 ]; then
echo "Finished, ${outputfile} is here."
else
echo "Error, filesize :${filesize}"
fi

clear-disk_identifier(ntsig).sh(NTシグニチャ(Disk identifier)をクリアする)

(2009-12-15追記)こちら是非お読み下さい。
NTシグニチャがどこにあるのかを日本語で検索すると、「NTシグニチャのクリアとはMBRの438バイト目から9バイトをすること」であるとの情報が始めの方にいくつか見つかると思います。これらは過去に私が書いたもので、実は厳密ではない情報です。MBRのそのあたりはNTシグニチャ以外の用途に使われていないので、9バイトだと思っていても支障が生じるわけではないのですが、正確にはその9バイトの中間あたりの(441バイト目からの)4バイトが厳密なNTシグニチャです。
NTシグニチャを書き込むスクリプト(ツール)は提供しません。パーティション構成の異なるディスク間で無理にNTシグニチャをコピーするとWindowsによってパーティションテーブルが破壊される事故が起きる場合があるからです。NTシグニチャのコピーなどは試みずに気軽にNTシグニチャをクリアすることをお薦めします。NTシグニチャをクリアするとドライブレターを振り直す必要が生じますが、事故に遭うよりはマシです。←(2013-6-11追記)このような“事故”はWindows 2000で発生しました。“現役”OSでは発生しません。パーティションを割り直した際には必ずNTシグニチャをクリアするというのが最も安全なハードディスクの使い方だと言えると思います。(同じディスクを複数のPCに取り付けたり頻繁にパーティション割りの変更をおこなったりする人以外は殆ど気にしなくてもいいレベルの話ではありますが...)
このスクリプトを実行すると

# "clear-disk_identifier(ntsig).sh"  /dev/sda
Current Disk identifier(NT Signature): 0xe4cee4ce
Proceed? yes or no [n]

このように現在のNTシグニチャの値が表示された上で確認を求めてきます。
ダウンロード fileclear-disk_identifier(ntsig).sh

[clear-disk_identifier(ntsig).sh]

#!/bin/sh -e
if test $# -lt 1; then
echo "eg. $0 /dev/sda"
exit
fi
echon() {
	printf "%s" "$@"
}
yesno()
{
	msg="$1"
	def="$2"
	while true ; do
	echon "$msg"
	read answer
	if [ "$answer" ] ; then
		case "$answer" in
		y|Y|yes|YES)
			return 0
			;;
		n|N|no|NO)
			return 1
			;;
		*)
			echo " "
			echo "Error: Invalid response, expected \"yes\" or \"no\"."
			continue
			;;
		esac
	else
		return $def
	fi
	done
}
printntsig()
{
echo -n "Current Disk identifier(NT Signature): 0x"
hexdump -s 442 -n 2 $1|head -1|cut -d" " -f2|tr -d '\12'
hexdump -s 440 -n 2 $1|head -1|cut -d" " -f2
}
bsig=`hexdump -s 510 -n 2 $1|head -1|cut -d" " -f2|tr -d '\12'`
if test "$bsig" != "aa55"; then
echo "Not a Valid Boot Sector"
exit
fi
printntsig $1
if yesno "Proceed? yes or no [n] " 1 ; then
dd if=/dev/zero bs=1 seek=440 count=4 of=$1 >/dev/null
if test $? -eq 0; then
echo "Done"
printntsig $1
fi
fi

get-disk_identifier(ntsig).sh(NTシグニチャ(Disk identifier)を表示する)

の機能を表示のみに絞った版です。

#!/bin/sh -e
if test $# -lt 1; then
echo "eg. $0 /dev/sda"
exit
fi
echo -n "Disk identifier(NT Signature): 0x"
hexdump -s 442 -n 2 $1|head -1|cut -d" " -f2|tr -d '\12'
hexdump -s 440 -n 2 $1|head -1|cut -d" " -f2

undup.sh(他の行に内包されない行のみを抽出する。レジストリキーやディレクトリの真の追加分を抽出する場合に使える)

(2007-12-29) 以前から告知のとおり、シェルスクリプトでやるべき処理ではないので削除しました。

 

※: ところでシェルスクリプト内のループでパイプを使うとパイプ以降(つまりループの中など(詳細は略))が別プロセスとなり、ループ内の変数値をループの外に伝えることはできません。そういう場合の一つの解決策は関数化です。ありきたりのサンプルが→ここにあります。
また、ヒアダイレクトを使ってシェルスクリプト内で新たなスクリプトなどを作成する例なんかがこのページにあります。
※:上の検索窓で「/bin/sh」を検索すれば当サイト内のシェルスクリプトを含むページが全て見つかります。

grepsjis.sh(SJISファイルを対象に日本語を検索)

eucJPとかutf-8な環境で中身がsjisのファイル群を日本語grepする為に作成したものです。
Webを検索せずに作ったので、他の人がこのような要件でどうしているかは知りません。
※これはutf-8環境用です。eucJPの場合は最後2行が異なります。
(2007-5-15)数ヶ月前に知りました。このような用途には以前から有名なPerlスクリプトがあるようです。
殆ど使ったことがないのですが、人によっては何かの助けになるでしょう。
(2008-3-1)放ったらかしにしていましたが、修正しました。

#!/bin/sh
LANG=ja_jp.SJIS
TMPC=
OPTS=
PATTN=
FILES=
parse_args()
{
for i in "$@" ; do
	if [ "$i" == "-" ]; then
		OPTS=${OPTS}" "${i}
		shift
		PATTN=${1}
		shift
		FILES="$@"
		return
	fi
	TMPC=`echo - ${i}|cut -b 3-3`
	if [ ${TMPC} != '-' ]; then
		PATTN=${1}
		shift
		FILES="$@"
		return
	fi
	OPTS=${OPTS}" "${i}
	shift
done
}
parse_args "$@"
PATTN=`echo "${PATTN}"|iconv -f UTF-8 -t CP932`
grep ${OPTS} "${PATTN}" ${FILES}|nkf -Sw

dvdbackup.sh(DVDリップ)

使わないので削除します。(2008-11-29)

textsearch.sh(自動でテキストファイルだけを選びディレクトリ以下丸ごと検索)

勝手のわからないOSで/以下を全て検索したりするときに使っています。※検索語の後にgrepに渡すオプションを付けます。
[textsearch.sh] (2008-12-3)最近のfileコマンドの仕様に合わせてアップトゥーデートしました。

#!/bin/sh
if [ $# -lt 1 ]; then
	echo "$0 SearchWord [Grep Option(eg. -i)]"
	exit 1
fi
exitproc()
{ rm -f ${TMPFILE}; }
trap '
exitproc
exit 1
' 2 15
SEARCH=$1
OPTION="-n $2"
TMPFILE=/tmp/$USER.grepwords
cat>$TMPFILE<<EOT
 text
 XML
EOT
echo -n "Current Path:"
echo `pwd`
echo "search word:${SEARCH}"
echo "Option:${OPTION}"
echo && echo && echo && echo
find . -type f|while read -r i
do file "${i}"|grep -f $TMPFILE> /dev/null && echo "${i}"
done|while read -r i
do grep ${OPTION} "${SEARCH}" "${i}" && echo "${i}" \
&& echo && echo && echo && echo
done
exitproc
echo -en '\a'>&2

通常、私はこのスクリプトをエディタ上で実行します。結果を取り込み、検索されたファイルに次々ジャンプします。

firefoxhtm.sh(htmlファイルとfirefoxの連携)2006-9-15 最近のfirefoxでは不要であることに気づきました

仮想端末やファイルブラウザ上でfirefoxでhtmlファイルを簡単に開くことができるようにするスクリプト
(2006-9-15) 最近のfirefoxでは不要であることに気づきました。
(2007-7-9) 削除しました。

download-radio.sh(cron登録してAM各局のmp3とかwmaとかを一気にダウンロードする)

ダウンロード download-radio.sh 2011-4-19更新
説明・中身を見るならこちら

all-process-asx.sh(cron登録してwebラジオを自動でローカルにダウンロードする)

ダウンロード all-process-asx.sh 2011-4-19更新 このスクリプトは単独では動きません。必ず説明ページで他に必要なスクリプトを一緒にダウンロードして下さい。
説明・中身を見るならこちら

download-nhk-gogakukouza.sh(cron登録してNHK語学講座を自動でローカルにダウンロードする)

ダウンロード download-nhk-gogakukouza.sh
説明・中身を見るならこちら

download-wma.sh(Windows Media形式のストリーミング放送をローカルにダウンロードした上でmp3形式のファイルも作成する)

(2009-12-1追記)以下の説明はこのスクリプトを単独で使用する場合用です。このスクリプトを部品として利用するもっと便利なものこのページにありますので、そちらもご覧下さい。
大げさな説明をすると、Windows上でGetASFStreamやNet Transportを使ってやれることをLinux上で可能とするスクリプトです。もちろんこの説明は大げさすぎで、本スクリプトは貧弱な機能しか持っていません。しかしLinux上で、しかもコマンドラインで利用できることが特徴(強み)です。
最近はポッドキャストやフラッシュを採用しているサイトが多くなってしまいWindows Media形式でストリーミングしているサイトは少ないと思います。NHKラジオの英会話はフラッシュ形式なのでこのスクリプトは使えません。
とりあえずこのスクリプトが使えるURLをいくつか挙げておきます。私にとってはめぼしい内容の放送が乏しいのでこのスクリプトの使いどころが今はあまりないという感じです。(2014-6-23)以下の例文で使用しているURLは2013年に廃止され、それらコンテンツはyoutube化されました。youtube化されたコンテンツの自動ダウンロードにはdownload-youtube.shをお使い下さい。

MBSラジオのありがとう浜村淳です(平日毎日更新)mms://mbs.sswmt1.smartstream.ne.jp/mbs/arigatou/arigatou[MMDD].wma
MBSラジオの押尾コータローの押しても弾いても(週一更新)mms://mbs.sswmt1.smartstream.ne.jp/mbs/oshio/oshio.wma
MBSラジオのヤングタウン日曜日(出演笑福亭鶴瓶、週一更新)mms://mbs.sswmt1.smartstream.ne.jp/mbs/yannichi/yannichi_[MMDD].wma

(2011-10-16追記)NHKラジオに関する情報は削除しました。NHKラジオのストリーミング放送に関してはこちらのページを利用して下さい。
このスクリプトはクーロンで定期的に起動してストリーミング放送を自動的にサーバ上に保存していく為のものです。
平日更新の放送であれば、たとえばcrontabに

00 17 * * 1-5 export PATH=$PATH:/home/disklessfun/bin;  (実際には改行しない)
download-wma.sh  (実際には改行しない)
mms://mbs.sswmt1.smartstream.ne.jp/mbs/arigatou/arigatou`date '+\%m\%d'`.wma  (実際には改行しない)
/somewhere > /somewhere/download-arigatou-`date '+\%Y\%m\%d\%H\%M'`.log 2>&1

と設定し、
週一更新の放送であれば、たとえばcrontabに

00 20 * * 2 export PATH=$PATH:/home/disklessfun/bin;  (実際には改行しない)
download-wma.sh  (実際には改行しない)
mms://mbs.sswmt1.smartstream.ne.jp/mbs/oshio/oshio.wma  (実際には改行しない)
/somewhere >/somewhere/download-oshio-`date '+\%Y\%m\%d\%H\%M'`.log 2>&1

とか

00 20 * * 3 export PATH=$PATH:/home/disklessfun/bin;  (実際には改行しない)
download-wma.sh  (実際には改行しない)
mms://mbs.sswmt1.smartstream.ne.jp/mbs/yannichi/(実際には改行しない)
yannichi_`date -d '3 days ago' '+\%m\%d'`.wma  (実際には改行しない)
/somewhere >/somewhere/download-yannichi-`date '+\%Y\%m\%d\%H\%M'`.log 2>&1

と設定しておくというわけです。同じURLのままで定期的に内容が変わってしまうストリーミング放送の聞き逃し対策として有効だと思います
このスクリプトを使用する為にはmplayerとlameをインストールしておく必要があります。更にget-wma-info.plスクリプトをパスの通った場所に置いておく必要があります。
言うまでもないことですが、ダウンロードして作成したファイルを自分で使用する限りは著作権法に全く違反しません。
現在NHKからダウンロードできるwmaにはヘッダにタイトルが書き込まれていないようです。その場合のローカルでのファイル名を決定する仕様はソースを参照して下さい。ソースは名前なしパイプの使用例でもあります。
(2009-9-15追記)簡単な重複ダウンロード・チェック機能を追加しました。
(2009-12-01追記)このページ用に大幅に改良しました。改良点の一つにWMA内の日本語タイトルに対応したことが挙げられます。
ダウンロード download-wma.sh  2014-6-23更新(内部で使用しているコマンドをmplayerからmplayer2に変更(これに伴い名前付きパイプの使用を廃止)。ファイル名無害化関数に%の処理を追加) 2012-4-2更新(スキップ部に-rfの記述を追加) 2012-3-11更新(asfbinコマンドを用いてWMVにインデックスを付加する記述を追加) 2010-3-28更新
※動作には下に掲載のget-wma-infoが必要
別の説明はこちら

transcode-wma-to-mp3.sh(wmaをmp3にトランスコードする)

ダウンロード transcode-wma-to-mp3.sh  2014-6-23更新(内部で使用しているコマンドをmplayerからmplayer2に変更(これに伴い名前付きパイプの使用を廃止)。ファイル名無害化関数に%の処理を追加) 2010-3-28更新
これの機能省略版で、このページの為に掲載しているだけです。
説明はもう少しこちらにも

get-wma-info.pl(WMAのヘッダ情報を取得するPerlスクリプト。シェルスクリプトから呼び出すヘルパースクリプトとして作成)

こちらで使用しています。
使用する為にはPerlのAudio::WMA拡張モジュールをインストールしておく必要があります。
Ubuntu系なら

# apt-get install cpanminus
# cpanm Audio::WMA

でインストールできます。
ダウンロード get-wma-info.pl  パスの通った場所に置いて下さい。
[get-wma-info.pl]

#!/usr/bin/perl
use strict;
use Audio::WMA;
my $type = $ARGV[0];
my $item = substr($ARGV[1],1);
my $file = $ARGV[2];
unless ( -e "$file" ) {die;}
my $wma = Audio::WMA->new($file);
if ($type eq "-info"){
my $info = $wma->info();
print "$info->{$item}"||die;
} elsif ($type eq "-tags"){
my $tags = $wma->tags();
print "$tags->{$item}"||die;
}

guess-partition-table.sh(ディスク表面を走査してパーティションテーブルを推測する)

試験的に作成したパーテョションテーブルを推量するシェルスクリプト(パーティションテーブルを修復するための情報を出力するためのスクリプトです。勝手にパーテョションテーブルを書き換えることはしません。)

  • fdisk -lの結果と見比べてみて下さい。
  • H(ヘッド)とS(トラック毎のセクタ数)の値は必ず指定しなければなりません。
  • パーティションテーブルは一切見ていません。
  • 同じ開始シリンダに(offset=0)と(offset=トラック毎のセクタ数)が並ぶ箇所は論理区画を意味しています。

こちらにまた別の、(詳しいかもしれない)説明があります。

 

ダウンロード fileguess-partition-table.sh このスクリプトを最初から組み込んだLinuxがこれです。

#!/bin/bash -e
exitproc()
{ umount $TMPDIR;rmdir $TMPDIR; }
trap '
exitproc
exit 1
' 2 15
getrawhs()
{
set +e
hdinfo="$(hdparm -i $DEVICE 2>/dev/null)"
if test $? -ne 0; then
USERHSMAND=true
else
set -e
for info in $hdinfo; do
case "$info" in *RawCHS=*) RawCHS="${info#RawCHS=}"; ;; esac
done
RawH=$(echo $RawCHS|cut -d"/" -f2)
RawS=$(echo $RawCHS|cut -d"/" -f3|sed 's/\,//')
fi
set -e
echo "RawHS=$RawH/$RawS"
}
analize_sector()
{
local cylinder=${1}
local offset=${2}
local start=$((cylinder + 1))
if (file $TMPDIR/$image|grep -iq "x86 boot sector") then
if (strings $TMPDIR/$image|grep -q NTFS) then
	type="NTFS Boot Sector"
elif (strings $TMPDIR/$image|grep -q MSWIN) then
	type="FAT Boot Sector"
elif (strings $TMPDIR/$image|grep -q GRUB) then
	type="GRUB Boot Sector"
else
	type=
fi
if [ $offset -eq -1 -a "$type" == "NTFS Boot Sector" ]; then
echo "   Cylinder $(($start - 1)) is NTFS End Cylinder"
$DEBUG && echo
else
echo -n "Start-Cylinder $start"
echo -en "\toffset $offset"
echo -e "\t$type"
$DEBUG && echo -n "SectorImage: "
$DEBUG && strings $TMPDIR/$image|tr -d '\012'
$DEBUG && (echo;echo)
fi
fi
return 0
}
DEVICE=$1
if [ $# -lt 2 ]; then
if [ $# -gt 0 ]; then
getrawhs
fi
echo "eg. $0 /dev/sda -HS=255/63"
echo "eg. $0 /dev/sda -HS=64/32"
echo "eg. $0 /dev/sda -HS=16/32"
echo "eg. $0 /dev/sda -HS=32/16"
echo "eg. $0 /dev/sda -HS=32/32"
echo "eg. $0 /dev/sda -HS=16/16"
exit 1
fi
DEBUG=false
USERHSMAND=false
HS=$2
devname=${DEVICE##*/}
LANG=C
# User specified HS
for x in $2; do
case "$x" in *-HS=*) hs="${x#-HS=}"; ;; esac
done
H=$(echo $hs|cut -d"/" -f1)
S=$(echo $hs|cut -d"/" -f2)
#H=${H:-$RawH}
#S=${S:-$RawS}
test "$S" = "" && exit
cylindersize=$(($H * $S))
wholesize=$(cat /sys/block/$devname/size)
cylinders=$(($wholesize / $cylindersize))
TMPDIR=`mktemp -d`
mount -t tmpfs -o "size=100k" tmpfs $TMPDIR
echo "Target Device: $DEVICE"
echo "Total Cylinders: $cylinders"
echo "H/S=$H/$S"
echo
for ((i=0;i<$cylinders;i++))
do
skipsectors=$(($i * $cylindersize ))
if [ $i -eq 0 ]; then
skipsectors=$(($skipsectors + $S))
fi
skipsectors=$(($skipsectors - 1))
dd if=$DEVICE count=1 of=$TMPDIR/1.img skip=$skipsectors 2>/dev/null
skipsectors=$(($skipsectors + 1))
dd if=$DEVICE count=1 of=$TMPDIR/2.img skip=$skipsectors 2>/dev/null
skipsectors=$(($skipsectors + $S))
dd if=$DEVICE count=1 of=$TMPDIR/3.img skip=$skipsectors 2>/dev/null
image=1.img
analize_sector $i -1
image=2.img
analize_sector $i 0
image=3.img
analize_sector $i $S
done
exitproc
exit 0

unzip.sh(zip, unzipの使い方)

zipのmanってわかりにくいですよね
でもWindowsのアーカイバと同じように圧縮するだけなら↓これだけです。

$ zip  -r  foo[.zip]  foo

ついでにunzipコマンドの(少し古い)ラッパースクリプトを掲載しておきます。
最近のunzipにもこのようなものが必要かどうかは調べていません。
Windows上で作成した複数のzipファイルをsambaサーバ上で連続して解凍するためのものです。
Windowsで圧縮したzipファイルを扱えるようにsmbfnconvコマンドを使用しています。内部SJISのzipファイルであればわりと正しくファイル名の文字コードを変換できます。smbfnconvを使わない仕様をデフォルトへと変更しました。
[unzip.sh]

#!/bin/sh
[ $# -lt 1 ] && echo "usage: $0 [-m(--mkdir)] zip-file(s)" && exit
# Normal color
NORMAL=""
# BLUE: Warning mesages
BLUE=""
MKDIR=false
while [ -n "${1}" ]
do
	case "${1}" in
	-m|--mkdir)MKDIR=true;shift;;
	-)shift;break;;
	*)break;;
	esac
done
while [ -n "${1}" ]
do
	if (file "${1}"|grep -iq "Zip archive") then
		dirname=`dirname "${1}"`
		basename=`basename "${1}"`
		filename=`basename "${1}" .zip`
		if [ "${filename}" != "${basename}" ]; then
#		$MKDIR && unzip -d "${dirname}/${filename}" "${1}" && \
#		smbfnconv -f cp932 -t utf-8 "${dirname}/${filename}"
		$MKDIR && unzip -d "${dirname}/${filename}" "${1}"
		! $MKDIR && unzip "${1}"
		else
			echo "${BLUE}Warning: ${1} does not have .zip extension."
			echo "Do nothing.${NORMAL}"
		fi
	else
		echo "${BLUE}Warning: ${1} is not Zip archive.${NORMAL}"
	fi
	shift
done

言うまでもないと思いますが、SJIS対応のunzipコマンドを使用する場合はsmbfnconvを記述している行の代りに、1行下の、現在コメントアウトしている行を使います。

1行スクリプトたち

スクリプトというより、よく使うコマンドを書き出しただけとも言えます。
ファイルブラウザに登録して使用するものを除けばaliasに登録するだけでもいいと思います。

cdrecord.sh(CD焼き用)(カーネル2.6用)

最近はdev=・・は要りませんが、まあ記録の意味で...

cdrecord -v dev=ATA:1,0,0 -dao -eject "${1}"

growisofs.sh(DVD焼き用)

(2015-10-29)BD環境にも対応する為/dev/dvdを/dev/cdromに修正(実デバイスは大概/dev/sr0)

growisofs -dvd-compat -Z "/dev/cdrom=${1}"

※:growisofsコマンドの大きな特徴はスマートにオンザフライに対応していることだと思います。ここでそのやり方を紹介しないのは私のメインマシンのCPU負荷が普段は高くてそのやり方をあまり使っていないからです。でも他のPC上でのバックアップの際にはgrowisofsを用いたオンザフライ焼きを活用しています。
あと、現状、LinuxでBDを焼く場合には上記growisofsの引数に「-use-the-force-luke=spare:none」を加えるのが普通です(理由説明は省略)。

erasecd.sh(CD消去用)(カーネル2.6用)

最近はdev=・・は要りませんが、まあ記録の意味で...

cdrecord -v dev=ATA:1,0,0 blank=fast -eject

erasedvd.sh(DVD消去用)

dvd+rw-format -blank /dev/dvd

firefoxlnk.sh(インターネットショットカットとfirefoxの連携)

ファイルブラウザ上でWindowsのインターネットショートカット(urlファイル)をダブルクリックするとfirefoxが当該ページを開いて起動します。※拡張子がurlのファイルの扱いについてファイルブラウザに登録しておく必要があります。仮想端末上でも使用できます。

$ firefoxlnk.sh hoge.url

みたいな感じで使用します。

 
exec firefox `egrep "^URL" "${1}"|cut -b 5-` &


残念ながら現在はhttpsに対応する為にワンライナーはやめました。

#!/bin/bash
line=$(egrep "^URL" "${1}")
exec firefox "${line#*=}"

mkudfiso.sh(生焼きDVD作成用)

生ペグDVD作成用等に使用しています。ファイルが入ったディレクトリを引数に取ります。(最近は-Jオプションは不要だと思うので私は使用していません)
(2008-12-30)最初のチェックは、今のところ互換性に問題のあるgenisoimageを使いたくないので設けてあります。
(2010-2-6)自分でも忘れていたのですが、自分で使用しているバージョンではファイル名が完全に保存されたかをチェックする機能を追加していました。ワンライナーの範疇から大きく逸脱しますがそのバージョンを紹介しておきます。
(2015-1-13)もう(とうの昔に)互換性の問題はほぼ心配しなくていいので(mkisofsの代わりに)genisoimageを使用する版に差し替えました。

#!/bin/sh -e
# Needed settings in /etc/sudoers.
#yourname	ALL=(ALL) NOPASSWD: /bin/mount
#yourname	ALL=(ALL) NOPASSWD: /bin/umount
genisoimage -V "$1" -allow-limited-size -r -o "$1.iso" "$1"
TMPFILE1=`mktemp`
TMPFILE2=`mktemp`
TMPDIR=`mktemp -d`
(cd "$1";ls -R>$TMPFILE1)
sudo mount -o loop,ro "$1.iso" $TMPDIR
(cd $TMPDIR;ls -R>$TMPFILE2)
sudo umount $TMPDIR
rmdir $TMPDIR
set +e
diff -u $TMPFILE1 $TMPFILE2
RET=$?
set -e
if test ${RET} -ne 0 ; then
echo "Error, At least one filename was not preserved."
fi
rm $TMPFILE1 $TMPFILE2
exit ${RET}

mkudfiso-2.sh(サイズが4G超のファイルを分割せずに焼きたい場合)

(2008-12-30)この方法は特に互換性が低くて、Windows XP,Windows 2000で中身を読めない(Vistaは知らない)ので、私としては、サイズが4096Mバイト以上4488Mバイトのファイルを分割せずに焼く場合専用の方法として使っています。4488Mバイト超のファイルの場合は1層に入りきらなくてどうせ分割が避けられないのでこの方法は使いません。この方法で作成したDVDはLinuxでLinuxでもWindowsでも読めます。私の場合Linux環境が常に近くにあって、分割したものを結合する手間よりもWindowsで読めないものをLinuxで読む手間の方が軽いのでこの方法を採用できています。(2010-03-04追記)久しぶりにこのオプションを利用してDVDを焼き、Windowsで読めるか試したところ、少し古い環境と言えるWindows 2000+BHA B's Recdorder 8.67の環境でも問題なく読めました。以前Windowsで読めなかったのは当時のgenisoimageの実装に問題があった為ではないかと思います。

#!/bin/sh
genisoimage -V $1 -allow-limited-size -r -o $1.iso $1

mkdvdiso.sh(DVD-Video作成用)

シュリンク後、DVDを再作成する際に使用しています。
(2007-5-15)ファイル名は自分の命名ルールに素直に従ってつけたものです。同名の有名なスクリプトと内容に関連はありません。
(2008-12-30)最初のチェックは、今のところ互換性に問題のあるgenisoimageを使いたくないので設けてあります。

#!/bin/sh
if test -L `which mkisofs`; then
echo "mkisofs is Symbolic Link" && exit
fi
mkisofs -V "$1" -dvd-video -o "$1.iso" "$1"

readline.sh(指定ファイルから指定行を抽出する)

$ readline.sh [ファイル名] [数字]

といった感じで使用します。

#!/bin/sh
count=0
while read i
do
count=`expr $count + 1`
[ $count -eq $2 ] && echo $i
done<$1

シェルスクリプトでやるとなると一応こうなると思いますが、行頭・行末がトリムされてしまうので通常はperlやawkを使うと思います。

おまけ(拡張子変換)

これは他と違い、単に構文の紹介だけです。どこにでも転がっているようなものだと思います。

for i in *.JPEG;do mv "$i" "`basename "$i" JPEG`jpg";done

高機能シェルだと内部コマンドだけで可能です。でも基本形はこんなものではないかと思います。
"chgext"みたいな名前で、2つの引数をとるシェルスクリプトにしてもいいでしょう。

modify-modifytime.sh (ファイルの更新時間を指定分ずらす)

MODTIME=`stat -c %y "$1"|sed 's/\-/\//g'|cut -b1-19`
touch -t `date -d "$MODTIME 32400 seconds" "+%Y%m%d%H%M.%S"` "$1"

ずらす時間を自由に指定できるスクリプトとして使用する場合は32400の部分を$2にします。
※:9時間後ろにずらすなら"32400 seconds"とか"9 hours"を指定し、9時間前にずらすなら、"32400 seconds ago"とか"9 hours ago"を指定すればいいわけです。

chgcaseall.sh(ファイル名を大文字小文字のいずれかに一気にそろえる)

多分同じ働きをするスクリプトはどこにでも転がっていると思いますが、これは独自に作成したものなので何らかの価値があるかもと思い掲載することにします。但しこれは下のchgcase.shを呼び出すだけです。オプションの指定が必須なのは安全装置の代わりです。

#!/bin/sh
[ $# -lt 1 ] && echo "$0 -u|-l" && exit 1
case "${1}" in
	-u|-l);;
	*)
	echo "$0 -u|-l" && exit 1
	;;
esac
find . ! -name "."|sort -r|while read i
do
chgcase.sh "${1}" "${i}"
done

chgcase.sh(ファイル名を大文字小文字のいずれかにそろえる)

何故、bashの機能を使っているか?ですが、後半のechoで"renaming.."と出力していている個所でfromとtoでパス表記の違いが生じないようにするにはこの方法が一番簡単だと思ったからです。

#!/bin/bash
[ $# -lt 2 ] && echo "$0 -u|-l filename" && exit 1
UPPER=false
case "${1}" in
	-u)UPPER=true;;
	-l);;
	*)
	echo "$0 -u|-l filename" && exit 1
	;;
esac
fname=${2##*/}
dirpath=${2%*/*}/
[ "${fname}/" == "${dirpath}" ] && dirpath=""
$UPPER && newfname=$(echo "${fname}"|tr \'[a-z]\' \'[A-Z]\')
! $UPPER && newfname=$(echo "${fname}"|tr \'[A-Z]\' \'[a-z]\')
if [ "${newfname}" != "${fname}" ]; then
echo "renaming \"${2}\" as \"${dirpath}${newfname}\""
mv "${2}" "${dirpath}${newfname}"
fi
 

ご要望、ご意見、質問を下のフォームにどうぞ
(でもここより、掲示板書き込みフォームのページに書いて頂いた方が気づき易いと思います。)

  • #Windowsのインターネットショートカット(.url)をlinuxでも開けるようにしたい。 -- jump? 2008-05-30 (金) 12:43:04
  • 既にここにそのやり方を書いてあります。 -- disklessfun? 2008-06-01 (日) 00:05:09
  • remove-empty-dir.sh は、rmdir -p <ディレクトリ名> ですね。 -- 1円切手? 2013-11-05 (火) 12:10:05
  • find . -type d -empty -print0 | xargs -0 rmdir とかでも良いかな? -- 1円切手? 2013-11-05 (火) 12:14:51
  • 2つとも違います。まあ、仮に同じであってもremove-empty-dir.shの掲載価値がなくなるわけではありません。 -- disklessfun? 2014-02-06 (木) 22:34:43