转贴自 http://www.fegensoft.com/fegensoft2002/seeksilence/Unix/6/2/2/2.htm
显然不能用mv *.ext1 *.ext2,shell会在真正执行mv命令之前处理掉通配符*,
只有当存在一个名为"*.ext2"的目录时,shell会执行下去,但已经不是你所期望的效果。首先解释一下basename命令,
basename string [ suffix ] ,basename会从string中删除所有/前缀,如果指定了后缀,也会从string删除掉。
#! /bin/csh
foreach file ( *.ext1 )
set base = `basename $file .ext1`
mv $file $base.ext2
end
#! /bin/csh
foreach file ( *.ext2 )
mv $file $file:r.ext1
end
#! /bin/sh
for file in *.ext2
do
base=`basename $file .ext2`
done
mv $file $base.ext1
#! /bin/ksh
do
for file in *.ext1
mv $file ${file%ext1}ext2
done
最后给个支持命令行参数的灵活些的ksh script
#! /bin/ksh
# 用法:命令 源后缀名 目的后缀名
if [ $# -ne 2 ]
then
echo "Usage: $0 sourceExt targetExt"
exit 1
fi
for file in *.
$1
do
mv $file ${file%$1}$2
done
此外下面是可以直接在命令行上完成的另外一种方法,如果你对sed命令了解就很清楚了:
ls -d *.ext1 | sed -e 's/.*/mv & &/' -e 's/ext1$/ext2/' | sh
ls -d *.ext2 | sed -e 's/.*/mv & &/' -e 's/ext2$/ext1/' | ksh
注意这种用法对于csh来说有问题,虽然转换依然成功,但会报告stty: : 无此设备或地址,原因我也不清楚。
for file in $(find . -name "*.del" -type f);do mv "$file" "${file%.del}";done
file=/dir1/dir2/dir3/my.file.txt
我们可以用 ${ } 分别替换获得不同的值:
${file#*/}:拿掉第一条 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}:拿掉最后一条 / 及其左边的字符串:my.file.txt
${file#*.}:拿掉第一个 . 及其左边的字符串:file.txt
${file##*.}:拿掉最后一个 . 及其左边的字符串:txt
${file%/*}:拿掉最后条 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/*}:拿掉第一条 / 及其右边的字符串:(空值)
${file%.*}:拿掉最后一个 . 及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}:拿掉第一个 . 及其右边的字符串:/dir1/dir2/dir3/my
//集体增加后缀
find . ! -type d |xargs -i mv {} {}.c;
find . ! -type d -exec mv -f {} {}.suf /;
要想把my.file.txt 变成 my.file.cpp
mv "$file" "${file%.*}.cpp"