2009年2月16日星期一

转贴: APUE, A Great Book

From:http://blog.solrex.cn/go/622676.html

这两周是选课试听期,还没有正式开始上课,所以有点空闲就翻了翻 UINX 环境高级编程(Advanced Programming in the UNIX Environment, 2e),看了七八章,发现这本书真的是无愧于"UNIX编程圣经"的称号。书中对编程中可能遇到的问题讲解得非常系统和详细,尤其当看到自己以前遇到过问题的地方时,简直就有一种顿悟的感觉,就想感叹一句"哦,原来如此!"。

我平常在写程序时,遇到问题总是求助于Google。对那些讲编程技巧的书向来不怎么感冒(尤其是中国人写的),总觉得那种书根本不适合花时间仔细看一遍。这种问题驱动式的学习方式固然在解决某一特定问题时显得快捷高效,但是也往往受限于一叶障目不见泰山的困境。在解决了某一问题之后,对其它同类问题没有足够关注,导致再遇到类似问题时仍需要去搜索答案。

问题驱动式的学习方式会导致对问题的了解不够系统和深入,但如果仅仅拿本大部头慢慢翻完的话,又会枯燥无味,而且体会也不深。我觉得读编程书的最好方法就是,先有一定量的实践,再去看书,而且要保持对书中习题和代码的练习量。有时候不妨先看实例代码再看正文解释,如果代码看得懂,看作者的解释是否和自己理解一样;如果代码看不懂,就会加深对正文的注意度。而且有时候读那些入门级的教科书,不妨只看代码。

当然,在编程的时候,桌子上应该有几本经典图书当作手册来参考,不时地重读一下某些章节会很有好处。像 APUE,我就觉得非常适合作为案头书,做 Linux/Unix开发的程序员买一本看看绝对不会失望。

毕业生必须知道:干部身份、三方协议、派遣证

本文系转贴,原帖地址为:http://cnc.byr.edu.cn/wForum/disparticle.php?boardName=Job&ID=522504&pos=564
原帖作者为Tritree (嚎月贪狼),感谢原帖作者。
===
[正文开始]

学校里关于毕业生的会也已经开了一大堆,耳朵也长膙了,嘴唇也磨薄了,很多人随大流听听看看,可真正重要的一些东西相信有很大一部分人却没有搞懂。如果不
信,你可以问问自己,什么叫三方协议?三方协议和谁签?有什么用?户口和三方又有什么关系?当一个个问题逐一提出来时,你可能已经开始觉得发虚。

在这里,我想简单的说一说我目前所知道的关于这方面的一些问题,相信肯定有很多不全面的地方,但至少相信可以帮帮你。

首先是大学毕业后的人生基本规划(本处所指为非在职考研、考博、考公务员等同学):

大学毕业后的一年最为关键,举例如2008年6月毕业7月正式工作者,其从08年7月到09年7月这一年是对其人生的基本规划最为重要的一年,原因涉及三项——三方协议、报到证(派遣证)、干部身份。

关于三方协议:

什么叫三方协议?网上答案都有,随便查查就知道了。但再深一些说呢,肯定有人不知道了。

三方协议,简单的讲就是学校、学生本人、工作单位三方就毕业生离校后就业工作落实所签署的一份协议书,很多人知道的是:三方协议过去必须签,但现在不一
定,三方签了只是学校统计就业率的一个参考指标。三方和派遣证挂钩,但我没有留京户口,单位签三方就要解决你的户口,所以现在单位都不签三方了,尤其是私
企等等。没错,上边说的都对,所以有些朋友们就把三方协议放弃了,而只是找到工作,自己去做个打工者,然后只考虑劳动合同。

那么究竟三方协议背后究竟还有什么呢?其实三方的背后还隐藏着很多。

如果说到三方协议,那么必需提到的就是派遣证与干部身份。

三方协议作为国家统计大学生就业率的一个根据,同时也是国家派遣证发放的一个证明。只有你签署了三方协议,拿回学校,学校才会在你毕业后将派遣证发给你,
而你拿着派遣证到你工作的单位报道,就此开始计算工龄,而你也就拥有了干部身份(每年基本6月25日毕业,所以6月18日前必需将三方交到学校)。

派遣证(报到证):

派遣证一式两份,一份是派遣证,另一部分是报到证。派遣证在你毕业后将放入你的档案,由国家直接打到你的单位(档案属国家机密,不允许个人持有。如果你的
用人单位拥有档案保存资格那么你的档案就放在单位,如果没有,那单位会掏钱将你的档案放在人才市场类的档案保存处。你过你没工作,那你的档案就直接打回原
籍)。而报到证则交由你手自行保管。在这里必须要重点说的是,很多人在毕业后没多久就把报到证丢了,而当若干年后单位希望将你提干要求出示报到证时,很多
就没有了,而只能再跑回某地去重新开证明,这时的证明可就没那么好开了,所以还是劝君保管好。

干部身份:

在中国社会体系中,公民分三中身份:农民、工人、干部。农民归农业部管理,工人归劳动局管理,而干部归人事局管理。大学生属于国家培养的专业人才,属于国
家干部身份。很多农村来的朋友家里都希望孩子通过念大学而改变祖辈农民的身份(这里没有贬低农民朋友的意思),而很多人却从毕业后就莫名其妙的丢了自己的
干部身份。当然也有很多是根本不在乎自己的干部身份。认为有就有,没有就没有,没有的话我至少是四年大学毕业学士学位。其实你错了。如果你没有留住你的干
部身份,可以说你的大学就是白念,而你只是个有学士学位的工人,根本没有改变你自己(就很多农村朋友来讲)。

干部身份靠什么来?靠三方协议,靠派遣证。派遣证就是你大学生干部身份的证明,假如某天你被提干时,这个就是你可以被提干的证明,因为你是干部身份。否则你就不能被提,因为你是工人。

也许很多人说:我不会被提干,那我要干部身份干嘛,我就想挣钱。

那么我现在要说的就是职称评定了。其中也涉及到关键一年的具体事宜。

大学生持报到证到单位上岗后,必须要经过一年的见习期(国家规定。相当于中专、大专的实习期)。见习期满后,本人必须记得要签"毕业生见习期考核鉴定表
",这是你转正的鉴定表(从此你就拿正常工资了),说明你已经是一个合格的人才了(见习期需要在同一单位完成,也就是你的三方、派遣证以及你的转正证明
表,这三个上面盖的要是同一单位的章,否则视为无效)。紧接着要记得填写"国家统一分配大中专院校毕业生专业技术职务任职资格认定表",也就是初级职称评
定表(这些事要你自己留心,没有人会提醒你去做的,表要到人事部网站下载)。具体可评定的职称可以到人事部网站上查询(职称最好和自己学的专业有联系,否
则到中高级评定时比较难)。现在我国职称评定这块要通过考试(除艺术、工艺美术、体育教练员及广播电视播音4个系列外,申报其他初级系列都需要通过考试才
能获得初级专业技术资格。考试采用闭卷笔答方式,实行统一大纲、统一命题、统一组织。申报人员参加北京市初级专业技术资格考试成绩合格,即可取得《北京市
专业技术资格证书》),以考试来决定你是否能评上职称。当然有些职称评定也不排除某些单位内部的人为原因。在你初级职称评完四年后,也就是你工作的第五
年,你可以申请评定中级职称。再五年后,也就是工作第十年,评定高级职称(具体可上网查)。这样你一辈子的职称就基本评定完了,所以有些幸运的人10年就
可以当上"高级工程师"。在我国,无论各行各业都会有职称评定,而且相信任何单位都希望有那些有职称的人来工作,而且,就算你工作的单位没有职称评定一
说,那想你如果是高级工程师,你拿的钱也绝对比别人多。而什么人能评定职称呢?有干部身份的人。所以从此看出,就算你不当官,你只挣钱,那干部身份对你来
说还是有用的。

说到这里,基本上一般的情况都讲完了。但有些人会问了,我不是本地生,我户口不能留这,没公司给我签三方,你说的都是屁话。呵呵,那你就错了。为什么不变
通的想想呢?例如:你在北京上学,但毕业后没有公司解决你的户口,怎么办?好办!在家里找公司签三方。因为你不能留京,所以你的户口会打回原籍,而档案与
户口不能脱离,所以你的档案也要打回原籍,而如果你想保住干部身份(但想在北京工作),那你就托人也好,请客也好在家找个单位把你的三方签了。然后其他和
上边一样,只是一年后记得回家去办转正与职称评定。如果嫌麻烦,没关系,你就回家就业,别担心回不来北京,因为如果你有职称,那么你就可以以后来京找工
作,而你也会属于人才流动,这时只要你提出单位也会适当解决你的户口问题,否则凭你打工者的身份要求单位解决你户口,梦吧你!

三方协议的签署是没有限制的,与任何公司或单位签都可以,不一定要国企或事业单位,否则每年那么多大学生就业,还不80%都要丢了干部身份,国家还不成白痴了。但要保证一点,就算是三个人的小公司也能签,但不要在一年内倒闭,否则你就没有人给你签转正了,切记切记。

又有人说了,我想考研,我明年要考,我就不签三方了,随便找个活干干,挣点钱完了。那你就大错特错了。(注意:此处考研并非指本科之后直接上研者,是指本科毕业后需要工作1年以上者)

记住,不论任何时候,别放弃你的身份!

如果你要考研,那么你属于在职考研一类,我们分类说一下。

假如你考上了:

你6月大学毕业,7月到单位报到。第二年7月,你转正,初级职称评定。研究生9月入学。当你研究生入学时,哥们已经是有身份的人了,3年研究生读完,哥们
出来直接拿正常工资了(进私企),没有见习期一说了(研究生毕业也有3个月的见习期)。如果你进国企或事业单位,那么研究生3年算工龄(我不知道私企是不
是,但国企或事业单位绝对是),你出来就可以评中级职称了,哥们又赚了一大笔。所以你说你该不该保你的干部身份?

假如你没考上:

没考上更简单,直接继续工作,回头等着评中级,没差什么。

很多人总是怕麻烦,其实一切就是这么简单,如果你做了,那么也许我的话会改变你的一生,如果你没做,那么就当给我捧场,也谢谢你,我们又少了一个竞争对手。不过要记住一句话,别因小失大,谨记!

bash快捷键

Ctrl-A 相当于HOME键,用于将光标定位到本行最前面

Ctrl-E 相当于End键,即将光标移动到本行末尾

Ctrl-B 相当于左箭头键,用于将光标向左移动一格

Ctrl-F 相当于右箭头键,用于将光标向右移动一格

Ctrl-D 相当于Del键,即删除光标所在处的字符

Ctrl-K 用于删除从光标处开始到结尾处的所有字符

Ctrl-L 清屏,相当于clear命令

Ctrl-R
进入历史命令查找状态,然后你输入几个关键字符,就可以找到你使用过的命令

Ctrl-U 用于删除从光标开始到行首的所有字符。一般在密码或命令输入错误时常用

Ctrl-H 删除光标左侧的一个字符

Ctrl-W 用于删除当前光标左侧的一个单词

Ctrl-P 相当于上箭头键,即显示上一个命令

Ctrl-N 相当于下箭头键,即显示下一个命令

Ctrl-T
用于颠倒光标所在处字符和前一个字符的位置。(目前不知道有什么作用,哪位朋友知道?)

Ctrl-J 相当于回车键

Alt-.
用于提取历史命令中的最后一个单词。你先执行history命令,然后再敲击此快捷键若干下,你就懂了!

Alt-BackSpace 用于删除本行所有的内容,基本上和Ctrl-U类似。

Alt-C
用于将当前光标处的字符变成大写,同时本光标所在单词的后续字符都变成小写。

Alt-L 用于将光标所在单词及所在单词的后续字符都变成小写。

Alt-U 用于将光标所在单词的光标所在处及之后的所有字符变成大写。

ps:使用bind -P命令可以查看所有键盘绑定。

ps2:Alt快捷键较少使用,因为常常和编辑器冲突

情景分析“C语言的const关键字”

C语言中的const一直是C语言初学者心中的痛,这是因为const在不同位置有不同作用,在不同情景有不同角色。这让初学者摸不清头脑。今天,和大家一起研究一下const,让它的每个角色都"深入人心"!

==============================================================================================

情景一:最简单的const用法

#include<stdio.h>
int main()
{
int const a;
a=5;
printf("a=%d\n",a);
return 0;
}

如果编译这个c文件,就会报错:

1071.c: In function 'main':
1071.c:5: error: assignment of read-only variable 'a'

显而易见,这是const在搞鬼,因为声明了const的变量是不能修改的!

如果将源代码修改为如下这样,就没有问题了!
#include<stdio.h>
int main()
{
int const a=5;
printf("a=%d\n",a);
return 0;
}

总结:const声明的变量必须要进行初始化赋值,如果错过这个机会,以后再想给const的变量赋值,可就没门了!切记~

PS:int const和const
int是一回事,"颠倒写"都是可以的。以后遇到了别犯晕,呵呵。但是,还是要留个心眼,当const和指针搀和到一起时,这个"颠倒写"的规律可未必成立。

==============================================================================================

情景二:发明const为了什么?

在const诞生之前,开发者一直使用#define VAR
100来定义一些有特殊用途的类常量,不过这样定义是存在一些劣势的。因此const应运而生,之后开发者可以使用const
int VAR=100;来定义类常量了。

至于为什么#define有其劣势,请参阅:http://dongpingli.blogspot.com/2009/02/define.html
:)
==============================================================================================

情景三:const和指针的配合是噩梦!

你能分辨得清这些声明么:
const int *A;
int const *A;
int *const A;
const int *const A;

如果有点犯晕的话,那就先给出它们的讲解,然后继续看后面的情景分析吧。

const int *A; //修饰指向的对象,A可变,A指向的对象不可变
int const *A;   //修饰指向的对象,A可变,A指向的对象不可变
int *const A;   //修饰指针A, A不可变,A指向的对象可变
const int *const A; //指针A和A指向的对象都不可变

==============================================================================================

情景四:const int *A

[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
const int *A=&num;
printf("result=%d\n",*A);
return 0;
}

编译执行结果为:

[rocrocket@wupengchong const_test]$ cc test1.c
[rocrocket@wupengchong const_test]$ ./a.out
result=12

接下来,我们动动手脚,在代码中加入了(*A)++;这条语句:

[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
const int *A=&num;
(*A)++;
printf("result=%d\n",*A);
return 0;
}

编译这个c文件:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
test1.c: In function 'main':
test1.c:6: error: increment of read-only location '*A'
可以看到,报错了,报错的内容表示"*A"是只读的,不能修改。

我们再修改一下源代码为下面这样:

[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
int tmp=100;
const int *A=&num;
A=&tmp;
printf("result=%d\n",*A);
return 0;
}

编译执行结果为:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
[rocrocket@wupengchong const_test]$ ./a.out
result=100

好了,如果你仔细看了这几个小得不能再小的程序,你自己都可以给出结论了!

结论:如果声明了const int
*A,那么A值是可以修改的,而*A是不可以修改的。更通俗的说,A指针可以随便指向一个整型,但只要被A盯上了的整型变量在使用*A引用时就不能修改了。

[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
int tmp=100;
const int *A=&num;
A=&tmp;
tmp=3;
printf("result=%d\n",*A);
return 0;
}

编译执行的结果为:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
[rocrocket@wupengchong const_test]$ ./a.out
result=3

结论2:即使A指向了tmp,我虽然不能修改*A,但是我仍然是可以用tmp来修改这个值的,完全不管*A的存在。呵呵

==============================================================================================

情景五:int *const A

[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
int *const A=&num;
printf("result=%d\n",*A);
return 0;
}

编译执行结果为:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
[rocrocket@wupengchong const_test]$ ./a.out
result=12

我们稍微修改下源代码:

[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
int tmp=100;
int *const A=&num;
A=&tmp;
printf("result=%d\n",*A);
return 0;
}

编译时报错了:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
test1.c: In function 'main':
test1.c:7: error: assignment of read-only variable 'A'
[rocrocket@wupengchong const_test]$ cat test1.c

可见A本身的值已经不能再变了。

继续修改源代码如下:

[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
int *const A=&num;
(*A)=100;
printf("result=%d\n",*A);
return 0;
}

编译执行结果为:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
[rocrocket@wupengchong const_test]$ ./a.out
result=100

可以看出,(*A)是可以改变的。

结论又可以轻易推出了:int *const A;   //const修饰指针A,
A不可变,A指向的对象可变

==============================================================================================

情景六:const int *const A; //指针A和A指向的对象都不可变

[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
int const *const A=&num;
(*A)=100;
printf("result=%d\n",*A);
return 0;
}

编译会报错:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
test1.c: In function 'main':
test1.c:6: error: assignment of read-only location '*A'

改下源代码:

[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
int tmp=100;
int const *const A=&num;
A=&tmp;
printf("result=%d\n",*A);
return 0;
}

编译仍然会报错:

[rocrocket@wupengchong const_test]$ !cc
cc test1.c
test1.c: In function 'main':
test1.c:7: error: assignment of read-only variable 'A'

呵呵,结论很明显了,const int *const A; //指针A和A指向的对象都不可变

当然const int *const A;和int const *const A=&num;是等价的!

情景七:如果const用在函数形参里呢?是不是又要复杂很多?

答案是NO!一点也不复杂。

来看看这个函数投:int addnum(const int num, int a, int b);

这个函数声明中的第一个形参是const int
num,这就表明如果我调用了这个函数,那么第一个实参被传到addnum函数里之后,就不能再做修改了!呵呵
就这么简单。

给个例子吧,让大家能更一目了然:

[rocrocket@wupengchong const_test]$ cat test2.c
#include<stdio.h>
int addto(const int num, int a, int b)
{
if(num==1){
return a+b;
}else{
return 0;
}
}

int main(){
int num=100;
int a=12,b=22;
int res;
num=1;
res=addto(num,a,b);
printf("res=%d\n",res);
return 0;
}

编译执行结果为:

[rocrocket@wupengchong const_test]$ !cc
cc test2.c
[rocrocket@wupengchong const_test]$ ./a.out
res=34

如果我修改一下,编译就会出错:

[rocrocket@wupengchong const_test]$ cat test2.c
#include<stdio.h>
int addto(const int num, int a, int b)
{
if(num==1){
num=3;
return a+b;
}else{
return 0;
}
}

int main(){
int num=100;
int a=12,b=22;
int res;
num=1;
res=addto(num,a,b);
printf("res=%d\n",res);
return 0;
}

编译报错为:

[rocrocket@wupengchong const_test]$ !cc
cc test2.c
test2.c: In function 'addto':
test2.c:5: error: assignment of read-only location 'num'

可见在函数里形参被声明为const的变量也是不能修改的哦!呵呵~

const其实不难,把本文的几个小例子看懂就OK了!

================================================================================
除了传递要求为const的参数以外,自己声明对象没有什么必须要加,但是对于一个逻辑上不应该被修改,应该为常量的对象,没有声明为const,就必须由程序员自己来维护,来记住这个变量不应该被修改,即使你不小心修改导致程序整体混乱了,编译器也不会报错
另,const和普通变量的声明存在于头文件时有区别,总之这些都是与你具体写程序的规划有关系,const这个玩意只是方便程序设计和程序编写,能够使程序更加的清晰,如果说我就是不爱用,就是喜欢一路变量用到底,那也没什么不行。。。

#define的坏处

在C++编程中应该尽量使用const和inline来代替#define,尽量做到能不用#define就不用。

#define常见的用途有"定义常量"以及"定义宏",但其中存在诸多的弊病。

第一,查错不直观,不利于调试。Define的定义是由预处理程序处理的,作的是完全的文本替换,不做任何的类型检查。在编译器处理阶段,define定义的东西已经被完全替换了,这样在debug的时候就看不到任何的相关信息,即跟踪时不能step
into宏。例如,把ASPECT_RATIO用define定义成1.653,编译器就看不到ASPECT_RATIO这个名字了。如果编译器报1.653错,那么就无从知道此1.653来自于何处。在真正编码的时候应该使用如下的语句来定义:
static const double ASPECT_RATIO = 1.653;

第二,没有任何类型信息,不是type
safe。因为它是文本级别的替换,这样不利于程序的维护。

第三,define的使用很容易造成污染。比如,如果有两个头文件都定义了ASPECT_RATIO,
而一个CPP文件又同时包含了这两个头文件,那么就会造成冲突。

更难查的是另外一种错误,比如有如下的代码:

// in header file def.h

#define Apple 1 #define Orange 2 #define Pineapple 3 …

// in some cpp file that includes the def.h

enum Colors {White, Black, Purple, Orange};

在.h文件中Orange被定义成水果的一种,而在.cpp文件中Orange又成为了一种颜色,那么编译器就会把此处的Orange替换成2,编译可能仍然可以通过,程序也能够运行,但是这就成了一个bug,表现出古怪的错误,且很难查错。

再比如定义了一个求a与b哪个数大的宏,

#define max(a,b) ((a) > (b) ?(a) : (b))

int a = 5, b = 0; max(++ a, b); max(++ a, b + 10);

在上面的操作中,max(++ a, b); 语句中a被++了两次,

而max(++ a, b + 10); 语句中a只加了一次,

这样在程序处理中就很有可能成为一个bug,且此bug也非常的难找。在实际编码时可以使用如下的语句来做:

template inline const T& max(const T& a, const T& b) { return a > b ? a :
b; }

more multiple file renaming goodness

From:http://www.basicallytech.com/blog/index.php?/archives/11-Shell-stuff-more-multiple-file-renaming-goodness.html

I had an e-mail from a guy named Devon telling me yet more ways to rename
multiple files. I thought they were pretty good (damn it!) and had to
share these new (to me) techniques.

These alternative methods seem to require the use of the Bash shell, so
some people may not wish to read any further!
remove a suffix

$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 algebra.txt
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 calculus.txt
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 equations.txt
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 geometry.txt
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 matrices.txt

Note the use of the "%" symbol to denote a suffix.

$ for FILE in *.txt; do mv -i "$FILE" "${FILE%.txt}"; done
$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 algebra
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 calculus
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 equations
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 geometry
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 matrices
change a suffix

$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 algebra.txt
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 calculus.txt
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 equations.txt
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 geometry.txt
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 matrices.txt

$ for FILE in *.txt; do mv -i "$FILE" "${FILE%.txt}.TXT"; done
$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 algebra.TXT
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 calculus.TXT
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 equations.TXT
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 geometry.TXT
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 matrices.TXT
remove a prefix

$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 maths_algebra
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 maths_calculus
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 maths_equations
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 maths_geometry
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 maths_matrices

For prefixes, replace the "%" with a "#".

$ for FILE in maths_*; do mv -i "$FILE" "${FILE#maths_}"; done
$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 algebra
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 calculus
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 equations
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 geometry
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 matrices
change a prefix

$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 maths_algebra
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 maths_calculus
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 maths_equations
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 maths_geometry
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 maths_matrices

$ for FILE in maths_*; do mv -i "$FILE" "MATHS_${FILE#maths_}"; done
$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 MATHS_algebra
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 MATHS_calculus
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 MATHS_equations
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 MATHS_geometry
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 MATHS_matrices

Thanks to Devon for that!

shell脚本对文件进行批量改名例子:
把当前文件夹下文件名含有eee的都改成大写的EEE,比如21-eee.doc就要改成21-EEE.doc。

for filename in *eee*
do
newname=`echo $filename|sed -n ’s/eee/EEE/p’`
mv $filename $newname
done

如果要将每个文件的执行权限去掉,这样写:
for filename in *; do chmod ugo-x $filename;done

rename multiple files on the command line

From:
http://www.basicallytech.com/blog/?/archives/10-Shell-stuff-rename-multiple-files-on-the-command-line.html#remove_spaces_tr

If you wish to quickly rename multiple files in a directory, a for loop
(sometimes combined with other utilities such as sed or tr) is one way to
do the job.

The examples in this article include removing spaces from filenames,
adding and removing suffixes and prefixes, and changing from uppercase to
lowercase.

Here is a full list of the examples I'm going to look at:
remove spaces from file names
alternative way to remove spaces from file names
add a suffix
add a prefix
remove a prefix
remove a suffix
uppercase to lowercase
uppercase to lowercase (suffix only)
an unlikely situation
remove spaces from file names

I've got some imaginary mp3 files with spaces in the file names. Spaces in
filenames are a bad idea. It's inconvenient, spaces are the delimiters
between command-line arguments, and for files you're putting out over the
Internet, it can cause other problems, so we're going to get rid of these
spaces as a matter of principle. (Whose foolish idea was it to put spaces
into filenames, anyway?)

$ ls -l
total 468
-rw-r--r-- 1 rob rob 15015 2006-10-20 11:18 01 - Some Song.mp3
-rw-r--r-- 1 rob rob 17313 2006-10-20 11:18 02 - Another Song.mp3
-rw-r--r-- 1 rob rob 17381 2006-10-20 11:19 03 - Yet Another Song.mp3
-rw-r--r-- 1 rob rob 410075 2006-10-20 11:19 04 - A New Song.mp3
-rw-r--r-- 1 rob rob 7327 2006-10-20 11:19 05 - Some Instrumental
Piece.mp3

I'm going to change the spaces to underscores. Since I don't want to mess
things up, I'll be cautious to begin with:

$ for FILE in *.mp3 ; do NEWFILE=`echo $FILE | sed 's/ /_/g'` ; echo
"$FILE will be renamed as $NEWFILE" ; done
01 - Some Song.mp3 will be renamed as 01_-_Some_Song.mp3
02 - Another Song.mp3 will be renamed as 02_-_Another_Song.mp3
03 - Yet Another Song.mp3 will be renamed as 03_-_Yet_Another_Song.mp3
04 - A New Song.mp3 will be renamed as 04_-_A_New_Song.mp3
05 - Some Instrumental Piece.mp3 will be renamed as
05_-_Some_Instrumental_Piece.mp3

That looks okay, so I'll try it for real.

$ for FILE in *.mp3 ; do NEWFILE=`echo $FILE | sed 's/ /_/g'` ; mv "$FILE"
$NEWFILE ; done
$ ls -l
total 468
-rw-r--r-- 1 rob rob 15015 2006-10-20 11:18 01_-_Some_Song.mp3
-rw-r--r-- 1 rob rob 17313 2006-10-20 11:18 02_-_Another_Song.mp3
-rw-r--r-- 1 rob rob 17381 2006-10-20 11:19 03_-_Yet_Another_Song.mp3
-rw-r--r-- 1 rob rob 410075 2006-10-20 11:19 04_-_A_New_Song.mp3
-rw-r--r-- 1 rob rob 7327 2006-10-20 11:19
05_-_Some_Instrumental_Piece.mp3

I realise that there is an alternative way, using tr, which is easier (to
type ). However I would argue that the principle of the above technique
(using sed) can be applied to more situations, making it more useful as a
template.

For those who are unfamiliar with the command line, I'm going to break
this down into it's constituent components. If you are familiar with this
sort of thing, feel free to skip down to the other examples.

This is not the place to discuss for loops in great detail. There are
loads of resources on the Internet for that sort of thing. When I was
starting to learn this stuff, I always found detailed analysis of these
things confusing, and that the best way to learn was to actually do it.

for FILE in *.mp3

In this part of the loop, FILE is the variable, and *.mp3 is the argument.
The for loop generates a variable for each argument until there are no
arguments left. In the example above, the variables generated are all the
files which match the regular expression *.mp3, in other words:
01 - Some Song.mp3
02 - Another Song.mp3
03 - Yet Another Song.mp3
04 - A New Song.mp3
05 - Some Instrumental Piece.mp3

; do

The semicolon is special character which allows you end one command and
run another command on the same line. Every for requires a do.

NEWFILE=`echo $FILE | sed 's/ /_/g'`

Now I'm creating a new variable called NEWFILE. sed is used to replace
each space in the name of the mp3 file referenced by FILE with an
underscore (s/ /_/g), so the variable NEWFILE is the same as FILE, except
the value of each variable has every space replaced with an underscore.

The next bit is the command we want to run on each argument:

mv "$FILE" $NEWFILE

Note that I put the loop-generated $FILE variable inside double-quote
marks for the mv command. This is required because of those spaces in the
original file name. If you don't do that the loop will try to run the
following command on each file:
mv 01 - Some Song.mp3 01_-_Some_Song.mp3

instead of
mv "01 - Some Song.mp3" 01_-_Some_Song.mp3

; done

Finally, every do requires a done.

Here are some other examples.
alternative way to remove spaces from file names

$ ls -l
total 468
-rw-r--r-- 1 rob rob 15015 2006-10-20 11:18 01 - Some Song.mp3
-rw-r--r-- 1 rob rob 17313 2006-10-20 11:18 02 - Another Song.mp3
-rw-r--r-- 1 rob rob 17381 2006-10-20 11:19 03 - Yet Another Song.mp3
-rw-r--r-- 1 rob rob 410075 2006-10-20 11:19 04 - A New Song.mp3
-rw-r--r-- 1 rob rob 7327 2006-10-20 11:19 05 - Some Instrumental
Piece.mp3

$ for FILE in *.mp3 ; do mv "$FILE" `echo $FILE | tr ' ' '_'` ; done
$ ls -l
total 468
-rw-r--r-- 1 rob rob 15015 2006-10-20 11:18 01_-_Some_Song.mp3
-rw-r--r-- 1 rob rob 17313 2006-10-20 11:18 02_-_Another_Song.mp3
-rw-r--r-- 1 rob rob 17381 2006-10-20 11:19 03_-_Yet_Another_Song.mp3
-rw-r--r-- 1 rob rob 410075 2006-10-20 11:19 04_-_A_New_Song.mp3
-rw-r--r-- 1 rob rob 7327 2006-10-20 11:19
05_-_Some_Instrumental_Piece.mp3
add a suffix to multiple files

$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 algebra
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 calculus
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 equations
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 geometry
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 matrices

In this example, I wish to add a .txt suffix to each file in this
directory.

We don't need sed here:

$ for FILE in * ; do mv $FILE $FILE.txt ; done
$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 algebra.txt
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 calculus.txt
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 equations.txt
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 geometry.txt
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 matrices.txt
add a prefix

Taking the files from the previous example:

$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 algebra.txt
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 calculus.txt
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 equations.txt
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 geometry.txt
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 matrices.txt

I wish to add a maths_ prefix to each file:

$ for FILE in * ; do mv $FILE maths_$FILE ; done
$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 maths_algebra.txt
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 maths_calculus.txt
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 maths_equations.txt
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 maths_geometry.txt
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 maths_matrices.txt
remove a prefix

Sticking with the files we've been using:

$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 maths_algebra.txt
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 maths_calculus.txt
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 maths_equations.txt
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 maths_geometry.txt
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 maths_matrices.txt

I've changed my mind about that maths_ prefix and want to remove it.

$ for FILE in * ; do NEWFILE=`echo $FILE | sed 's/^maths_//'` ; mv $FILE
$NEWFILE ; done
$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 algebra.txt
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 calculus.txt
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 equations.txt
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 geometry.txt
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 matrices.txt

The ^ symbol in sed matches the start of a line.
remove a suffix

While I'm at it, I think I'll remove the suffix as well.

$ for FILE in *.txt ; do NEWFILE=`echo $FILE | sed 's/.txt$//'` ; mv $FILE
$NEWFILE ; done
$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 algebra
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 calculus
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 equations
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 geometry
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 matrices

The $ symbol in sed matches the end of a line.
uppercase to lowercase

$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 ALGEBRA
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 CALCULUS
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 EQUATIONS
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 GEOMETRY
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 MATRICES

$ for FILE in * ; do mv $FILE `echo $FILE | tr '[A-Z]' '[a-z]'` ; done
$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 algebra
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 calculus
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 equations
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 geometry
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 matrices
uppercase to lowercase (suffix only)

$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 Algebra.TXT
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 Calculus.TXT
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 Equations.TXT
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 Geometry.TXT
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 Matrices.TXT

$ for FILE in *.TXT ; do NEWFILE=`echo $FILE | sed 's/.TXT$/.txt/'` ; mv
$FILE $NEWFILE ; done
$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 Algebra.txt
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 Calculus.txt
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 Equations.txt
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 Geometry.txt
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 Matrices.txt
an unlikely situation

Finally, an unlikely situation. I have a bunch of files with multiple
spaces and capitalised suffixes. I want the spaces changed to an
underscore, except where there are two or more consecutive spaces, where I
want just a single underscore. While we're at it, if a space is next to
the dot of a prefix, let's just remove it. I also want to make the
suffixes lowercase. Hmm.

$ ls -l
total 20
-rw-r--r-- 1 rob rob 201 2006-10-23 23:44 A file with many spaces.TXT
-rw-r--r-- 1 rob rob 1579 2006-10-23 23:44 Another wierdly named file.TXT
-rw-r--r-- 1 rob rob 1452 2006-10-23 23:44 My mate Arron spels beter than
this.txt
-rw-r--r-- 1 rob rob 924 2006-10-23 23:44 Not really.TXT
-rw-r--r-- 1 rob rob 379 2006-10-23 23:44 Whoo named this .TXT

I'm not going to try to correct the spelling as well!

$ for FILE in * ; do NEWFILE=`echo $FILE | sed -e 's/.TXT$/.txt/' -e 's/[
]*[ ]/_/g' -e 's/_[.]/./g'` ; mv "$FILE" $NEWFILE ; done
$ ls -l
total 20
-rw-r--r-- 1 rob rob 201 2006-10-23 23:44 A_file_with_many_spaces.txt
-rw-r--r-- 1 rob rob 1579 2006-10-23 23:44 Another_wierdly_named_file.txt
-rw-r--r-- 1 rob rob 1452 2006-10-23 23:44
My_mate_Arron_spels_beter_than_this.txt
-rw-r--r-- 1 rob rob 924 2006-10-23 23:44 Not_really.txt
-rw-r--r-- 1 rob rob 379 2006-10-23 23:44 Whoo_named_this.txt

That was somewhat contrived, but it does provide an example of the power
of the command line.

Bear in mind that some people pay for this sort of functionality. Mind
you, consider their option.
addendum

It occurred to me after I wrote this article that some one might want to
emulate the windows option.

Giving all the files the same name, but with a different number seems,
well, foolish, but let's do it anyway. Parentheses are also a bad idea in
filenames, but this is just an exercise.

$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 algebra
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 calculus
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 equations
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 geometry
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 matrices

$ NUM=0 ; for FILE in * ; do NUM=`expr $NUM + 1` ; mv $FILE
foolish\($NUM\) ; done
$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 foolish(1)
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 foolish(2)
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 foolish(3)
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 foolish(4)
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 foolish(5)

What might be more useful would be to retain the original name and
seperate it from the sequential number with a much more command-line
friendly underscore.

$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 algebra
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 calculus
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 equations
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 geometry
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 matrices

$ NUM=0 ; for FILE in * ; do NUM=`expr $NUM + 1` ; mv $FILE ${FILE}_$NUM ;
done
$ ls -l
total 20
-rw-r--r-- 1 rob rob 733 2006-10-20 13:23 algebra_1
-rw-r--r-- 1 rob rob 194 2006-10-20 13:23 calculus_2
-rw-r--r-- 1 rob rob 117 2006-10-20 13:23 equations_3
-rw-r--r-- 1 rob rob 402 2006-10-20 13:23 geometry_4
-rw-r--r-- 1 rob rob 50 2006-10-20 13:23 matrices_5

Happy renaming.