Subject: How do I rename "*.foo" to "*.bar", or change file names to lowercase?
Date: Thu Mar 18 17:16:55 EST 1993

2.6) "*.foo" というファイルネームを全部 "*.bar" というファイルネームに変え たり、アルファベットを小文字にしたりするにはどうすれば良いのですか。

なぜ "mv *.foo *.bar" だとできないのでしょうか。シェルがどうやってワイ ルドカードを展開しているか考えて下さい。"*.foo" と "*.bar" は、mv コマ ンドが引数を読む前に展開されます。シェルによって、二つの点で失敗するこ とがあります。csh は "*.bar" にマッチするファイルがないので "No matcsh." を表示します。sh なら、たった一つの "*.bar" という名前のディレクトリが 存在する、なんてことがあった場合にのみ、"mv a.foo b.foo c.foo *.bar" を実行します。しかしこれはあり得そうになく、ほとんど確実にあなたがやろ うとしていることとは違うでしょう。

それぞれのシェルに依存しますが、ループを使って各ファイルごとに "mv" を 実行すれば、質問の動作を行なうことができます。使っているシステムに "basename" があるなら、このようにできます。

C Shell:
foreach f ( *.foo )
set base=`basename $f .foo`
mv $f $base.bar
end

Bourne Shell:
for f in *.foo; do
base=`basename $f .foo`
mv $f $base.bar
done

"basename" を使う代わりに独自の変数置換機能を持っているシェルもありま す。それなら、このようなもっと簡単なループが使えます。

C Shell:
foreach f ( *.foo )
mv $f $f:r.bar
end

Korn Shell:
for f in *.foo; do
mv $f ${f%foo}bar
done

もし "basename" がない、または *.foo を *.bar に改名するのと似たような ことをやりたいなら、元のファイル名をばらすのに "sed" のようなものを使 う方法もあります。しかしループさせる考え方全体は同じです。'sed' を使っ てファイル名を "mv" コマンドに変換し、実行するために "sh" に渡します。

ls -d *.foo | sed -e 's/.*/mv & &/' -e 's/foo$/bar/' | sh
この作業をうまくやる、Vladimir Lanin の "mmv" というプログラムが comp.sources.unix(Volume 21, issues 87 and 88)に1990年4月に投稿されま した。

mmv '*.foo' '=1.bar'
上のようなシェルループは、ファイル名を大文字から小文字、またはその逆の 変換に使うこともできます。もし大文字のファイル名から小文字のファイル名 に変えるなら、このようにすれば良いのです。

C Shell:
foreach f ( * )
mv $f `echo $f | tr '[A-Z]' '[a-z]'`
end

Bourne Shell:
for f in *; do
mv $f `echo $f | tr '[A-Z]' '[a-z]'`
done

Korn Shell:
        
typeset -l l
for f in *; do
l="$f"
mv $f $l
done

もしあなたが完璧主義で、(空白などを含む) 変な名前のファイルを扱いたい 時は、これを使う必要があるでしょう。

g=`expr "xxx$f" : 'xxx¥(.*¥)' | tr '[A-Z]' '[a-z]'`
'expr' コマンドは、例え名前が '-n' とか、'¥c' の様な System V のエスケー プシーケンスを含んでいる時でさえ、常にファイル名として表示するでしょう。

"tr" のバージョンによって、[ や ] が必要なものとそうでないものがありま す。この上記の例にそれらを含ませるのは良くないかもしれせん。[] を要求 しないバージョンのtrは、'[' を '[' に(A-Z は a-z に)、']' は ']' に変 換すれば良いのだな、と都合良く考えるでしょう。

"perl" がインストールされていれば、Larry Wallのリネームスクリプトがと ても便利だと思うでしょう。これは広く様々なファイル名変更を行なうのに使 えます。

    
#!/usr/bin/perl
#
# rename script examples from lwall:
#    rename 's/¥.orig$//' *.orig
#    rename 'y/A-Z/a-z/ unless /^Make/' *
#    rename '$_ .= ".bad"' *.f
#    rename 'print "$_: "; s/foo/bar/ if <stdin> =‾ /^y/i' *

$op = shift;
for (@ARGV) {
    $was = $_;
    eval $op;
    die $@ if $@;
    rename($was,$_) unless $was eq $_;
}

UNIX FAQ LIST / Copyright(c)1994,Ted Timar / tmatimar@isgtec.com


Maintainer: あさだ たくや