最近学着用Linux上网,结果经常忘了网址,就mount上c盘,打开windows/favorites/用notepad打开???.url,再Ctrl+c和Ctrl+v,才浏览上该网址,但很不方便。于是就想把书签都从*.url中提取出来,可是用”Ctrl cv”大法不是办法,太麻烦了,现在什么事情都要“自动化”,因此就着手编个程序来实现。
大概原理:
从起始目录搜索各个子目录,用GAWK从各个url文件中把网址提取出来,用重定向符“>”存成文件。
首先,来介绍一下GAWK。GAWK是一个资料处理的程序,能用相当简短的语句来完成字符串处理功能。现在以”CPCW网站.url”文件为例,介绍一下。
CPCW网站.url有以下内容
[DEFAULT]
BASEURL=http://www.cpcw.com/
[InternetShortcut]
URL=http://www.cpcw.com/
Modified=2098A2DAC868BF0124
在shell中输入gawk /url/ {print $0} CPCW网站.url
输出如下:
BASEURL=http://www.cpcw.com/
URL=http://www.cpcw.com/
Gawk格式为: gawk ‘表达式 {动作} 表达式 {动作}…..' 要处理的文件1 文件2…..
Gawk 读入文件首先以内部变量RS为分界符,把文件内容分成一个一个记录,再以FS把记录分解成栏位。一个记录的第一个栏位为$1,第二个为$2…..$0为该记录。Gawk一个一个记录地处理,如果符合任意一个表达式,就会执行该表达式后面的动作。
常见表达式有以下几个:
xxxxx/ {print $0} 只要记录有字符串xxxxx,就输出该记录。
$1= =match {print $2} 如果记录的第一个栏位是match,就输出第二个栏位。除了==,还有&&,||,!学过C的一定不会陌生!
回到正题,怎样提取http://www.cpcw.com/ 呢?只要把栏位分界符FS设为”=”,如果$1==”URL”,那$2就是网址了。整条命令为:
gawk 'BEGIN {FS="="} $1=="URL" {print $2}'
BEGIN 后面的动作唯一开始就强行执行的,类似的还有END
接着就是文件操作,这里主要是打开目录,获得目录中的文件名,用到函数有:
#include
DIR *opendir(char *pathname); //打开成功返回一目录指针
struct dirent *readdir(DIR *dirptr); //返回指向结构dirent的指针dirent->d_name为一字符
//数组,存放着该目录中的文件名,调用一次readdir(),
//d_name就存放下一个文件名,当返回0时,表明已经读完了。
int closedir(DIR *dirptr); //工作完成后,别忘了关闭连接
其次,就要判断一个文件名是文件还是目录:
#include
int stat(char *pathname,struct stat *sbuf); //调用之后,sbuf.st_mode存放文件类型值
// if (sbuf.st_mode&S_IFMT==S_IFDIR) 是目录
// else 不是目录
本程序采用递归的方式,找到一个目录,就进入搜索,否则就调用system()执行shell命令
使用方法:
比如,书签放在/c/windows/Favorites/下,输出文件为/home/url
就执行 程序名 /c/windows/Favorites/ /home/url
使用的时候才发现,由于gawk的限制,文件名中不能有空格,+,&等符号,也是要我修改,不过收获也挺多!如果有疑问,就email给我一起交流 (penly@21cn.com)
附:源程序
#include
#include
#include
#include
#include
char command[60];
char rootdir[50]; //起始目录
char pwd[500]; //pwd为当前目录
char output[20];
main(int argc,char *arg[])
{
DIR *d;
strcpy(rootdir,arg[1]);
strcpy(pwd,rootdir);
strcpy(command,"gawk 'BEGIN {FS=\"=\"} $1==\"URL\" {print $2}'");
strcpy(output,arg[2]);
if (d=opendir(rootdir))
chuli(d);
}
chuli(DIR *d)
{
struct dirent *link;
char temp[300];
char bakpwd[300];
strcpy(bakpwd,pwd); //保存当前目录,供递归后恢复pwd
link=readdir(d); /*skip . */
link=readdir(d); /*skip .. */
while((link=readdir(d))!=0)
{
if (isdir(link->d_name)==S_IFDIR)
{ //是目录,改变当前目录,进入该目录,递归
sprintf(pwd,"%s%s/",bakpwd,link->d_name);
chuli(opendir(pwd));
}
else
{ // “>>”为重定向符,向指定文件追加内容
sprintf(temp,"%s %s%s>>%s",command,pwd,link->d_name,output);
system(temp);
}
strcpy(pwd,bakpwd); //恢复pwd
}
closedir(d);
return;
}
isdir(char *name)
{
struct stat sbuf;
char temp[200];
sprintf(temp,"%s%s",pwd,name);
stat(temp,&sbuf);
return (sbuf.st_mode)&S_IFMT;
}