`

Unix下子目录的模糊跳转

阅读更多
原文来自:http://www2.ccw.com.cn/01/0115/c/0115c05_2.asp

在DOS或Unix操作系统下,当要进入某个子目录时,一般要输入包括绝对路径在内的全名,如果目录名较长,操作起来就会比较麻烦。这点对于经常使用Unix操作系统的人来说,体会尤为深刻。由于Unix下目录树结构错综复杂,有不少子目录,其全路径名长度可达100多个字符。而且,Unix对大小写敏感,要进入这种大小写混杂,且还可能含有其他符号的超长子目录,确实很麻烦。更麻烦的是,Unix不像DOS提供了丰富的命令行编辑功能,定义了诸多的功能键 (F1~F4、Esc、Ins、Del等),输错了可以按F3重复上一条命令并进行编辑。在Unix下一旦输错了中间的一个字符,就得全部重新输入!

那么,能不能找到一种更简洁的进入子目录的方法呢?答案是肯定的。笔者经过实践,设计了一个子目录模糊跳转的程序来代替Unix下的“cd”命令,使得Unix下子目录的跳转变得非常方便。下面介绍这一命令的实现方法。

程序功能

该命令的功能包括:首先,不用输入绝对路径;其次,不用输入目录全名。只要输入该目录名的前若干个字符即可(姑且称这种跳转方式为“普通模糊跳转方式”)。或者只输入该目录名中间的若干个字符(也就是说,不必从第一个字符开始匹配,称这种跳转方式为“高度模糊跳转方式”)。例如,我们要进入如下子目录时:

/usr/agent/ydcommunication/senddir/onl_serv

在“普通模糊跳转方式”下不管当前目录在哪里,只要在命令提示符下键入:

j onl

或用“j on”甚至“j o”均可进入该目录。当符合条件的目录有多个时,就在屏幕上列出所有符合条件的目录供选择。

如程序被设置为“高度模糊跳转方式”,只需键入:

j ser

“高度模糊跳转方式”提供了一种更为自由的跳转子目录的方式。但这种方式也有弊端,主要是同等条件下匹配的目录可能会更多。在本文介绍的方法中这个功能是可选的,可以用开关参数“-t”来进行普通模糊和高度模糊两种跳转方式的转换,用哪种跳转方式,由用户决定。

编程实现

程序文件为jj.c,部分代码如下:

#ifndef PATH_MAX

#define PATH_MAX 255

#endif

#define ENTER 0x0a

#define ESC 0x1b

#define SPACE 0x20

#define ROWS 20 /*每页显示的最大行数*/

#define MSGLINE 22

#define MAX_C 75 /*每行显示的最大字符数*/

char curdir[32],wholedir[PATH_MAX];

FILE *fp;

/*主函数*/

main(int argc,char *argv[])

{

int result=0;

initscr();refresh();

if(argc==2&&argv[1][0]==‘-’&&toupper(argv[1][1])==‘S’)

result=searchdir(0);

else if(argc==2&&argv[1][0]==‘-’'&&toupper(argv[1][1])==‘L’)

result=jumpdir(“ ”,1);

else if(argc==2&&argv[1][0]==‘-’&&toupper(argv[1][1])==‘T’)

result=turn();

else if(argc==2&&argv[1][0]!=‘-’)

result=jumpdir(argv[1],0);

else

{

mvprintw(3,10,“用法:j -s(搜索所有的目录信息)”);

mvprintw(4,10,“或者:j -l(列出所有的目录信息)”);

mvprintw(4,10,“或者:j -t(普通模糊和高度模糊跳转方式的转换)”);

mvprintw(5,10,“或者:j 目录名(跳转到指定目录)”);

mvprintw(6,10,“快速目录跳转工具 1.1 Unix 版本”);

mvprintw(8,10,“(C)版权所有 彭茂山 2000.08.21”);

mvprintw(9,10,“Email:pms@163.net ICQ:12846890 OICQ:17000112”);

mvprintw(10,10,“谢谢使用!”);

refresh();

}

echo();

endwin();

if(result) exit(-1);

exit(0);

}

/*跳转处理函数*/

jumpdir(char cdir[32],int kg)

{

FILE *fp1;

char ch,wdir[ROWS][PATH_MAX];

int i=0,j,k=0,flag=0,flag1=0;

if((fp=fopen(“/tmp/dir.inf”,“r”))==NULL)

{

mvprintw(3,10,“请先用-s参数搜索目录信息!”);

refresh();

fclose(fp);

return(-1);

}

if((fp1=fopen(“/tmp/dir1.inf”,“w”))==NULL)

{

mvprintw(3,10,“无法打开文件/tmp/dir1.inf\n”);

refresh();

fclose(fp);

fclose(fp1);

return(-1);

}

fscanf(fp,“%s”,curdir);

fflush(fp);

if(!strcmp(curdir,“!!!!!!”)) flag1=1;

else rewind(fp);

do /*开始do循环*/

{

if(k >: = ROWS) {i=0;k=0;flag=1;}

while(!feof(fp))

{

fscanf(fp,“%s%s”,curdir,wholedir);fflush(fp);

if(flag1) /*高度模糊跳转*/

{

if(kg||strstr(curdir,cdir)!=NULL)

/*列出所有符合条件的目录,如用-l参数,则kg=1,不管条件是否符合,都列出所有目录*/

{

strcpy(wdir[i],wholedir);

k+=strlen(wdir[i])/MAX_C+1;

i++;

}

}

else /*普通模糊跳转*/

{

if(kg||!strncmp(curdir,cdir,strlen(cdir))){

strcpy(wdir[i],wholedir);

k+=strlen(wdir[i])/MAX_C+1;

i++;

}

}

/*控制每屏显示的行数*/

if(k >:= ROWS) break;

}/*结束while(!feof(fp))*/

/*只有一条目录符合条件*/

if(i==1&&!flag)

{

/*将要跳转的目录名写到/tmp/dir1.inf中*/

fprintf(fp1,“%s”,wdir[0]);

fclose(fp);

fclose(fp1);

return(0);

}

else if(i!=0)

{

clear();

k=0;

for(j=0;j<:i;j++)

{

system(“setcolor red”);

mvprintw(k,0,“[%c]”,j+‘A’);

refresh();

system(“setcolor white”);

mvprintw(k,3,“->:%s”,wdir[j]);

refresh();

k+=strlen(wdir[j])/MAX_C+1;

}

system(“setcolor red”);

mvprintw(k+1,0,“<:Enter>:”);

refresh();

if(!feof(fp)) {

system(“setcolor white”);

mvprintw(k+1,7,“下一页,”);

refresh();

}

else {

system(“setcolor white”);

mvprintw(k+1,7,“中断,”);

refresh();

}

system(“setcolor red”);

mvprintw(k+1,14,“<:ESC>:”);refresh();

system(“setcolor white”);

mvprintw(k+1,19,“中断,”);refresh();

system(“setcolor red”);

mvprintw(k+1,24,“<:Space>:”);refresh();

system(“setcolor white”);

mvprintw(k+1,31,“-”);refresh();

system(“setcolor red”);

mvprintw(k+1,33,“[A]”);refresh();

system(“setcolor white”);

mvprintw(k+1,36,“,”);refresh();

system(“setcolor red”);

mvprintw(k+1,37,“<:A>:”);refresh();

system(“setcolor white”);

mvprintw(k+1,40,“->:”);refresh();

system(“setcolor red”);

mvprintw(k+1,42,“<: %c >:”,‘A’+i-1);refresh();

system(“setcolor white”);

mvprintw(k+1,46,“跳转到相应目录,请选择:”);refresh();

ch=getch();

/*选择错,请重新输入*/

while((toupper(ch)<:‘A’||toupper(ch)>:=‘A’

+i)&&ch!=ESC&&ch!=ENTER&&(!isspace(ch)))

{

beep();

mvprintw(MSGLINE,0,“选项输入错,正确选项是:A->:%c\n”,‘A’+i-1);

refresh();

move(k+1,70);

ch=getch();

}

}/*结束 else if(i!=0) */

}while(ch==ENTER&&!feof(fp));

clear_in(MSGLINE);

if(ch==ESC||ch==ENTER&&feof(fp)){

mvprintw(MSGLINE,0,“用户中断, 谢谢使用!”);

refresh();

fclose(fp);

fclose(fp1);

return(0);

}

if(isalpha(ch)) ch=toupper(ch);

if(isspace(ch)) ch=‘A’;

if(i>:0)

fprintf(fp1,“%s”,wdir[ch-‘A’]);

else {

mvprintw(22,0,“目录未找到!\n”);

refresh();

return(-1);

}

fclose(fp);

fclose(fp1);

return(0);

}/*结束jumpdir()函数*/

/*查找匹配目录*/

searchdir()

{

if((fp=fopen(“/tmp/dir.inf”,“w”))==NULL){

mvprintw(MSGLINE,0,“文件dir.inf打不开”);

refresh();

return(-1);

}

clear_in(MSGLINE);

mvprintw(MSGLINE,0,“正在搜索目录信息,时间可能比较长,请耐心等候...\n”);

refresh();

/*调用搜索子目录的递归子函数*/

shdir(“/”);

clear_in(MSGLINE);

mvprintw(MSGLINE,0,“目录搜索完毕!”);

refresh();

fclose(fp);

return(0);

}

/*搜索子目录的递归子函数*/

shdir(char *sdir)

{

DIR *dirp;

char wholedir[PATH_MAX];

struct dirent *dirment;

struct stat statbuf;

char olddir[PATH_MAX];

getcwd(olddir,PATH_MAX);

if((dirp=opendir(sdir))==NULL) return(-1);

chdir(sdir);

while((dirment=readdir(dirp))!=NULL)

{

stat(dirment->:d_name,&statbuf);

/*是子目录(不包括.和..子目录)*/

if((statbuf.st_mode&S_IFDIR)&&(statbuf.st_mode<:20000)&&strcmp(dirment->:d_name,“.”)&&strcmp(dirment->:d_name,“..”))

{

getcwd(wholedir,PATH_MAX);

if(wholedir[strlen(wholedir)-1]==‘/’)

{strcat(wholedir,dirment->:d_name);}

else {

strcat(wholedir,“/”);

strcat(wholedir,dirment->:d_name);

}

/*将所有的目录信息写到/tmp/dir.inf中*/

fprintf(fp,“%-34s%2s%s\n”,dirment->:d_name,“ ”,wholedir);

/*调用递归子函数*/

fflush(fp);

shdir(dirment->:d_name);

}

}/*结束while*/

chdir(olddir);

closedir(dirp);

return(0);

}

clear_in(int i)

{move(i,0);clrtoeol();}

/*查找模式转换处理*/

turn()

{

FILE *fp1;

char buf[290];

if((fp=fopen(“/tmp/dir.inf”,“r”))==NULL){

mvprintw(3,10,“请先用-s参数搜索目录信息!”);

refresh();

fclose(fp);

return(-1);

}

if((fp1=fopen(“/tmp/tmpf”,“w”))==NULL)

{

mvprintw(3,10,“无法打开文件/tmp/dir1.inf\n”);

refresh();

fclose(fp);

fclose(fp1);

return(-1);

}

fgets(buf,290,fp);

if(strncmp(buf,“!!!!!!”,6))

{

rewind(fp);

fputs(“!!!!!!\n”,fp1);

}

while(!feof(fp)) fputc(fgetc(fp),fp1);

fclose(fp);

fclose(fp1);

system(“mv /tmp/tmpf /tmp/dir.inf”);

if(strncmp(buf,“!!!!!!”,6)){

mvprintw(3,10,“OK,现在已转成高度模糊跳转方式.”);

refresh();

}

else {

mvprintw(3,10,“OK,现在已转成普通模糊跳转方式.”);

refresh();

}

return(0);

}

其他处理

该程序可用如下命令编译(在SCO OpenServer 5.05下编译通过):

cc -o jj jj.c -lcurses -lc

基于Unix下子进程的修改对父进程无效的特性,让上述程序在主程序中直接实现子目录的跳转尚有困难。为此,笔者先在主程序中只生成目标目录的全路径名,存于文件/tmp/dir1.inf中,然后再编一个shell程序ju做进一步处理。

j()

{

>: /tmp/dir1.inf

/etc/jj $1

dir=`cat /tmp/dir1.inf|awk ‘{print $1}’`

if [ “$dir” = “” ]then

return

else

cd $dir

echo $dir

echo Success!

fi

}

该shell程序的作用是定义一个私有函数j(),该函数将根据/tmp/dir1.inf的内容实现对子目录的跳转。将jj和ju两个文件拷入/etc目录下,用如下命令将两个文件的权限改为最大:

chmod 777 /etc/jj /etc/ju

这样就使任何用户都有使用权限。

最后,修改各用户的.profile文件,在该文件最后追加一句:

 ./etc/ju (注意:“.”和“/etc/ju”之间有个空格)

这样处理后,就可以用“j”(注意:是“j”而不是“ju”)命令来代替“cd”命令了。最后还要注意的是,第一次使用时,要用“-s”参数扫描目录信息,并把扫描结果存于文件/tmp/dir.inf中。如果以后目录结构发生改变,也要重新扫描目录信息。
分享到:
评论

相关推荐

    unix实验三 目录树的遍历

    unix实验三 目录树的遍历 henxiangxi

    UNIX网络操作系统实验报告 广工

    在用户主目录下,新建子目录,子目录名为:专业和班级(可以是拼音)。 3. 在新建的子目录下完成全部练习,所有的操作练习均要截图显示。 4. 所有的实验内容必须在命令行方式下进行操作。 5. 纸制版的封面单面打印,...

    精通UNIX下C语言 源码

    《精通UNIX下C语言编程》 书源代码 精通UNIX下C语言精通UNIX下C语言精通UNIX下C语言

    unix编程艺术(带目录高清版本)

    unix编程艺术(带目录高清版本),高清原版,unix编程艺术(带目录高清版本),高清原版

    UNIX环境高级编程(带目录版本)

    书中除了介绍UNIX文件和目录、标准I/O库、系统数据文件和信息、进程环境、进程控制、进程关系、信号、线程、线程控制、守护进程、各种I/O、进程间通信、网络IPC、伪终端等方面的内容,还在此基础上介绍了多个应用...

    Basic Unix commands

    cd ~/unix转到主目录的unix下 6 ls 【选项】【文件|目录】 显示指定目录中的文件和子目录信息。不指 定目录时,显示当前目录下的文件和子目录信息; -a 显示所有文件 -l 显示文件和子目录的详细信息 查看权限 -t...

    unix命令子文件3

    unix命令子文件,unix命令子文件

    unix下oracle命令.zip

    unix下oracle命令,能帮助你解决一些在UNIX下操作数据库的问题

    unix命令子文件2

    unix命令子文件,unix命令子文件

    unix下C编程源码

    unix下C编程源码,unix下C编程源码,欢迎下载!

    Unix下的FTP客户端

    之所以封装这个类是因为以前在unix下写文件上传下载的操作都是调shell脚本,C、C++很难控制与shell的交互, 并且无法获知出错的错误代码,用C++封装成一个工具类后,任何项目都可以重用了。 操作很方便,就...

    windows下的unix

    直接在windows下使用unix的程序。直接安装使用!附带说明书。

    Unix教程基础篇 Unix基础教程

    基础篇 Unix教程 U N I X通常可以分为四个主要部分:内核、s h e l l、文件结构和应用程序。内核是运行程 序和管理磁盘、打印机等硬件...按目录的方式管理,每个目录可以包含任何数目的子目录,每个子目录可包含文件。

    UNIX网络编程 卷1 (目录版)

    unix网络编程(第三版),本人亲自撰写PDF目录,使用得心应手!

    unix下vi命令详解

    很受用 可以看看 主要详细介绍sco unix 下的vi的各种命令

    Unix第四章 UNIX下的C语言开发环境

    对Unix系统的简单介绍,本章为UNIX下的C语言开发环境,主要介绍了GCC,GDB和MAKE命令。

    UNIX操作系统电子讲义

    UNIX操作系统电子讲义,UNIX基本管理入门讲义,UNIX管理基本的命令.

    Unix 下 C语言开发

    Unix 下 C语言开发,方便以后的学习与发展。大概介绍。请多指教

    精通UNIX下C语言编程及项目实践

    精通UNIX下C语言编程及项目实践,精通UNIX下C语言编程及项目实践

    UNIX目录及文件操作命令

    此文档包含UNIX基本命令 第一章 目录及文件操作命令 ls、pwd、cd、grep等 第二章 设备管理 stty、lp等 第三章 进程管理 sleep、ps、kill等 第四章 系统管理和用户管理 who、 whodo、passwd等 第五章 通信和...

Global site tag (gtag.js) - Google Analytics