shell编程菜鸟教程(编写shell脚本的基本步骤是什么)

:暂无数据 2026-08-06 08:30:01 :0

shell编程菜鸟教程(编写shell脚本的基本步骤是什么)

今天给各位分享编写shell脚本的基本步骤是什么的知识,其中也会对编写shell脚本的基本步骤是什么进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录

编写shell脚本的基本步骤是什么

shell脚本只是命令操作的集合。就是把你手动交互输入的命令放在一个文件里,自动依次执行。

步骤大约如下:
1. 在行首指定shell脚本的解析器,如 #!/bin/bash
2. 接着依次每行输入shell的操作命令
3. 输入完毕后,给文件设置可执行权限并运行。

Shell的简单编程

$cat test.sh
#!/bin/bash
if [ -c $1 ];then
echo “$1是字符设备文件“
else test -e $1 || echo “This file is not exist“
fi
if test -d $2;then
echo “$2是目录文件“
for file in `ls $2/*.c`
do
ls -l $file
done
else test -e $2 || echo “This file is not exist“
fi
$./test.sh ddd.c test
test是目录文件
-rw-rw-r--. 1 flycat flycat 0 1月 1 21:20 test/aaa.c
-rw-rw-r--. 1 flycat flycat 0 1月 1 21:20 test/bbb.c
-rw-rw-r--. 1 flycat flycat 0 1月 1 21:20 test/ccc.c

简单的shell编程

#include 《unistd.h》
#include 《sys/types.h》
#include 《sys/wait.h》
#include 《stdlib.h》
#include 《sys/stat.h》
#include 《fcntl.h》

#define BUFFERSIZE 80

extern char *get_current_dir_name(void);
extern char *getenv(const char *name);
extern pid_t waitpid(pid_t pid, int *status, int options);

char buffer[BUFFERSIZE+1];

main()
{
char *path, *arg, *input;
int li_inputlen, is_bj, is_back, i, j, k, pid, status;
char lc_char;

while (1){
/* initiations */
is_bj = 0; /*redirection flag*/
is_back = 0; /*background*/

/* shell prompt */
path = get_current_dir_name();
printf(“%s》$“,path);

/*开始获取输入*/
li_inputlen = 0;
lc_char = getchar();
while (lc_char !=’\n’){
if(li_inputlen 《 BUFFERSIZE)
buffer[li_inputlen++] = lc_char;
lc_char = getchar();
}

/*命令超长处理*/
if (li_inputlen 》= BUFFERSIZE){
printf(“Your command is too long! Please re-enter your command!\n“);
li_inputlen = 0; /*reset */
continue;
}
else
buffer[li_inputlen] = ’\0’;/*加上串结束符号,形成字串*/

/*将命令从缓存拷贝到input中*/
input = (char *) malloc(sizeof(char) * (li_inputlen+1));
strcpy(input,buffer);

/* 获取命令和参数并保存在arg中*/
for (i = 0,j = 0,k = 0;i 《= li_inputlen;i++){
/*管道和重定向单独处理*/
if (input[i] == ’《’ || input[i] == ’》’ || input[i] ==’|’){
if (input[i] == ’|’)
pipel(input,li_inputlen);
else
redirect(input,li_inputlen);
is_bj = 1;
break;
}
/*处理空格、TAB和结束符。不用处理‘\n’,大家如果仔细分析前面的获取输入的程序的话,
*不难发现回车符并没有写入buffer*/
if (input[i] == ’ ’ || input[i] ==’\t’ || input[i] == ’\0’){
if (j == 0) /*这个条件可以略去连在一起的多个空格或者tab*/
continue;
else{
buffer[j++] = ’\0’;
arg[k] = (char *) malloc(sizeof(char)*j);
/*将指令或参数从缓存拷贝到arg中*/
strcpy(arg[k],buffer);
j = 0; /*准备取下一个参数*/
k++;
}
}
else{
/*如果字串最后是‘&’,则置后台运行标记为1*/
if (input[i] == ’&’ && input[i+1] == ’\0’){
is_back = 1;
continue;
}
buffer[j++] = input[i];
}
}

free(input);/*释放空间*/

/*如果输入的指令是leave则退出while,即退出程序*/
if (strcmp(arg,“leave“) == 0 ){
printf(“bye-bye\n“);
break;
}
/*如果输入的指令是about则显示作者信息,同时结束本条命令的解析过程*/
if (strcmp(arg,“ about“) == 0 ){
printf(“copyright by shike,shike13@163.com\n“);
continue;
}

if (is_bj == 0){ /*非管道、重定向指令*/
/*在使用xxec执行命令的时候,最后的参数必须是NULL指针,
*所以将最后一个参数置成空值*/
arg[k] = (char *) 0;
/*判断指令arg是否存在*/
if (is_fileexist(arg) == -1 ){
printf(“This command is not found?!\n“);
for(i=0;i《k;i++)
free(arg[i]);
continue;
}

/* fork a sub-process to run the execution file */
if ((pid = fork()) ==0) /*子进程*/
execv(buffer,arg);
else /*父进程*/
if (is_back == 0) /*并非后台执行指令*/
waitpid(pid,&status,0);

/*释放申请的空间*/
for (i=0;i《k;i++)
free(arg[i]);
}
}
}

int is_fileexist(char *comm)
{
char *path,*p;
int i;

i = 0;
/*使用getenv函数来获取系统环境变量,用参数PATH表示获取路径*/
path = getenv(“PATH“);
p = path;
while (*p != ’\0’){
/*路径列表使用‘:’来分隔路径*/
if (*p != ’:’)
buffer[i++] = *p;
else{
buffer[i++] = ’/’;
buffer[i] = ’\0’;
/*将指令和路径合成,形成pathname,并使用access函数来判断该文件是否存在*/
strcat(buffer,comm);

if (access(buffer,F_OK) == 0) /*文件被找到*/
return 0;
else
/*继续寻找其它路径*/
i = 0;
}
p++;
}
/*搜索完所有路径,依然没有找到则返回-1*/
return -1;
}

int redirect(char *in,int len)
{
char *argv,*filename;
pid_t pid;
int i,j,k,fd_in,fd_out,is_in = -1,is_out = -1,num = 0;
int is_back = 0,status=0;

/*这里是重定向的命令解析过程,其中filename用于存放重定向文件,
*is_in, is_out分别是输入重定向标记和输出重定向标记*/
for (i = 0,j = 0,k = 0;i 《= len;i++){
if (in[i]==’ ’||in[i]==’\t’||in[i]==’\0’||in[i] ==’《’||in[i]==’》’){
if (in[i] == ’》’ || in[i] == ’《’){
/*重定向指令最多’《’,’》’各出现一次,因此num最大为2,
*否则认为命令输入错误*/
if (num 《 3){
num ++;
if (in[i] == ’《’)
is_in = num - 1;
else
is_out = num - 1;

/*处理命令和重定向符号相连的情况,比如ls》a*/
if (j 》 0 && num == 1) {
buffer[j++] = ’\0’;
argv[k] = (char *) malloc(sizeof(char)*j);
strcpy(argv[k],buffer);
k++;
j = 0;
}
}
else{
printf(“The format is error!\n“);
return -1;
}
}
if (j == 0)
continue;
else{
buffer[j++] = ’\0’;
/*尚未遇到重定向符号,字符串是命令或参数*/
if (num == 0){
argv[k] = (char *) malloc(sizeof(char)*j);
strcpy(argv[k],buffer);
k++;
}
/*是重定向后符号的字符串,是文件名*/
else{
filename[status] = (char *) malloc(sizeof(char)*j);
strcpy(filename[status++],buffer);
}
j = 0; /*initate*/
}
}
else{
if (in[i] == ’&’ && in[i+1] == ’\0’){
is_back = 1;
continue;
}
buffer[j++] = in[i];
}
}

argv[k] = (char *) 0;

if (is_fileexist(argv) == -1 ){
printf(“This command is not founded!\n“);
for(i=0;i《k;i++)
free(argv[i]);
return 0;
}

if ((pid = fork()) ==0){
/*存在输出重定向*/
if (is_out != -1)
if((fd_out=open(filename[is_out],O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR))==-1){
printf(“Open out %s Error\n“,filename[is_out]);
return -1;
}

/*存在输入重定向*/
if (is_in != -1)
if((fd_in=open(filename[is_in],O_RDONLY,S_IRUSR|S_IWUSR))==-1){
printf(“Open in %s Error\n“,filename[is_out]);
return -1;
}

if (is_out != -1)
/*使用dup2函数将标准输出重定向到fd_out上,dup2(int oldfd,int newfd)实现的
*是把oldfd所指的文件描述符复制到newfd。若newfd为一已打开的文件描述词,
*则newfd所指的文件会先被关闭,dup2复制的文件描述词与原来的文件描述词
*共享各种文件状态*/
if(dup2(fd_out,STDOUT_FILENO)==-1){
printf(“Redirect Standard Out Error\n“);
exit(1);
}

if (is_in != -1)
if(dup2(fd_in,STDIN_FILENO)==-1){
printf(“Redirect Standard Out Error\n“);
exit(1);
}
execv(buffer,argv);
}
else
if (is_back == 0) /*run on the TOP*/
waitpid(pid,&status,0);

for (i=0;i《k;i++)
free(argv[i]);

if (is_in != -1){
free(filename[is_in]);
close(fd_in);
}
if (is_out != -1){
free(filename[is_out]);
close(fd_out);
}
return 0;
}

int pipel(char *input,int len)
{
char *argv;
int i,j,k,count,is_back = 0;
int li_comm = 0,fd,fpip;
char lc_char,lc_end;
pid_t child1,child2;

/*管道的命令解析过程*/
for (i = 0,j = 0,k = 0;i 《= len;i++){
if (input[i]== ’ ’ || input[i] == ’\t’ || input[i] == ’\0’ || input[i] == ’|’){
if (input[i] == ’|’ ) /*管道符号*/
{
if (j 》 0)
{
buffer[j++] = ’\0’;
/*因为管道连接的是两个指令,所以用二维数组指针来存放命令和参数,
*li_comm是表示第几个指令*/
argv[li_comm][k] = (char *) malloc(sizeof(char)*j);
strcpy(argv[li_comm][k++],buffer);
}
argv[li_comm][k++] = (char *) 0;
/*遇到管道符,第一个指令完毕,开始准备接受第二个指令*/
li_comm++;
count = k;
k=0;j=0;
}
if (j == 0)
continue;
else
{
buffer[j++] = ’\0’;
argv[li_comm][k] = (char *) malloc(sizeof(char)*j);
strcpy(argv[li_comm][k],buffer);
k++;
}
j = 0; /*initate*/
}
else{
if (input[i] == ’&’ && input[i+1] == ’\0’){
is_back = 1;
continue;
}
buffer[j++] = input[i];
}
}
argv[li_comm][k++] = (char *) 0;

if (is_fileexist(argv) == -1 ){
printf(“This first command is not found!\n“);
for(i=0;i《count;i++)
free(argv[i]);
return 0;
}
/*指令解析结束*/

/*建立管道*/
if (pipe(fd) == -1 ){
printf(“open pipe error!\n“);
return -1;
}

/*创建第一个子进程执行管道符前的指令,并将输出写到管道*/
if ((child1 = fork()) ==0){
/*关闭读端*/
close(fd);
if (fd != STDOUT_FILENO){
/*将标准输出重定向到管道的写入端,这样该子进程的输出就写入了管道*/
if (dup2(fd,STDOUT_FILENO) == -1){
printf(“Redirect Standard Out Error\n“);
return -1;
}
/*关闭写入端*/
close(fd);
}
execv(buffer,argv);
}
else{ /*父进程*/
/*先要等待写入管道的进程结束*/
waitpid(child1,&li_comm,0);
/*然后我们必须写入一个结束标记,告诉读管道进程数据到这里就完了*/
lc_end = 0x1a;
write(fd,lc_end,1);
close(fd);

if (is_fileexist(argv) == -1 ){
printf(“This command is not founded!\n“);
for(i=0;i《k;i++)
free(argv[i]);
return 0;
}

/*创建第二个进程执行管道符后的指令,并从管道读输入流 */
if ((child2 = fork()) == 0){
if (fd != STDIN_FILENO){
/*将标准输入重定向到管道读入端*/
if(dup2(fd,STDIN_FILENO) == -1){
printf(“Redirect Standard In Error!\n“);
return -1;
}
close(fd);
}
execv(buffer,argv);
}
else /*父进程*/
if (is_back == 0)
waitpid(child2,NULL,0);
}
for (i=0;i《count;i++)
free(argv[i]);
for (i=0;i《k;i++)
free(argv[i]);
return 0;
}

以前写的,好像一些细节不一样,不明白的地方,发邮件给我,shike13@163.com

菜鸟入门问题:shell 与“终端”是什么

Shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行。
实际上Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核。不仅如此,Shell有自己的编程语言用于对命令的,它允许用户编写由shell命令组成的程序。Shell编程语言具有普通编程语言的很多特点,比如它也有循环结构和分支控制结构等,用这种编程语言编写的Shell程序与其他应用程序具有同样的效果。  
Linux提供了像Microsoft Windows那样的可视的命令输入界面(也就是你说的终端),Window是图形用户界面(GUI)。它提供了很多窗口管理器。
你的理解虽然不是很规范,但在你目前的阶段,完全可以这么理解!

求更好的shell脚本初学者的教程(免费的)并且求各位大拿给初学者点建议

其实shell脚本非常简单,以前chianitlab曾经录制过linux教学视频,包含了一些shell变成方面的知识,不过我认为还是太基础了。我建议你还是看书,先看《Shell脚本学习指南》《实战LINUX+SHELL编程与服务器管理》有了一些shell的基础,在看《高级Bash脚本编程指南》,写shell脚本一定会涉及到sed、awk、正则表达式,然后在看《sed and awk》《精通正则表达式》。

OK,关于shell编程菜鸟教程和编写shell脚本的基本步骤是什么的内容到此结束了,希望对大家有所帮助。

shell编程菜鸟教程(编写shell脚本的基本步骤是什么)

本文编辑:admin

更多文章:


dropdownlist 绑定(DropDownList 绑定所有项 并 显示指定项)

dropdownlist 绑定(DropDownList 绑定所有项 并 显示指定项)

本篇文章给大家谈谈dropdownlist 绑定,以及DropDownList 绑定所有项 并 显示指定项对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

2026年10月11日 08:50

协方差计算公式(协方差的计算公式)

协方差计算公式(协方差的计算公式)

这篇文章给大家聊聊关于协方差计算公式,以及协方差的计算公式对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。

2026年10月11日 08:10

易语言网页api接口怎么调用(易语言,怎么读取网页json的api)

易语言网页api接口怎么调用(易语言,怎么读取网页json的api)

本篇文章给大家谈谈易语言网页api接口怎么调用,以及易语言,怎么读取网页json的api对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。

2026年10月11日 08:00

majority of(the majority of 和 a majority of的区别以及用法例句)

majority of(the majority of 和 a majority of的区别以及用法例句)

这篇文章给大家聊聊关于majority of,以及the majority of 和 a majority of的区别以及用法例句对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。

2026年10月11日 07:40

汉字机内码查询表(1个汉字的机内码是几位谢谢)

汉字机内码查询表(1个汉字的机内码是几位谢谢)

大家好,关于汉字机内码查询表很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于1个汉字的机内码是几位谢谢的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮助!

2026年10月11日 07:20

promote翻译(英语翻译倡导怎么说)

promote翻译(英语翻译倡导怎么说)

其实promote翻译的问题并不复杂,但是又很多的朋友都不太了解英语翻译倡导怎么说,因此呢,今天小编就来为大家分享promote翻译的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!

2026年10月11日 06:30

用手机如何导航?开车用手机导航哪个软件最好

用手机如何导航?开车用手机导航哪个软件最好

今天给各位分享用手机如何导航的知识,其中也会对用手机如何导航进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

2026年10月11日 06:20

多线程技术有什么用(多线程有什么作用)

多线程技术有什么用(多线程有什么作用)

其实多线程技术有什么用的问题并不复杂,但是又很多的朋友都不太了解多线程有什么作用,因此呢,今天小编就来为大家分享多线程技术有什么用的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!

2026年10月11日 05:40

another time(another time和other time的区别)

another time(another time和other time的区别)

大家好,another time相信很多的网友都不是很明白,包括another time和other time的区别也是一样,不过没有关系,接下来就来为大家分享关于another time和another time和other time的区

2026年10月11日 05:00

java开发工具包jdk(JDK是什么意思)

java开发工具包jdk(JDK是什么意思)

其实java开发工具包jdk的问题并不复杂,但是又很多的朋友都不太了解JDK是什么意思,因此呢,今天小编就来为大家分享java开发工具包jdk的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!

2026年10月11日 04:50

最近更新

repercussions(都是余波,repercussions和aftermath有什么区别啊)
2026-10-11 09:00:05 浏览:0
dropdownlist 绑定(DropDownList 绑定所有项 并 显示指定项)
2026-10-11 08:50:04 浏览:0
majority of(the majority of 和 a majority of的区别以及用法例句)
2026-10-11 07:40:02 浏览:0
热门文章

标签列表