基于C语言实现Linux风格Shell的目录切换异常问题求助
自定义Shell目录显示问题修复
问题现象
开发的自定义Shell在执行cd命令切换目录后,提示符能正确显示目标目录,但执行其他命令(如cat file1.txt)后,提示符会错误回退到家目录。运行示例:
./main 1730sh:~$ cd Ghioalda-Edward-p3 1730sh:~Ghioalda-Edward-p3$ cat file1.txt 1730sh:~$
当前代码
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> #include <fcntl.h> #include <string.h> #define BUFFERSIZE 1024 int main(int argc, char* argv[]) { char buf[BUFFERSIZE]; int n; printf("1730sh:~$ \n"); while ((n = read(STDIN_FILENO, buf, BUFFERSIZE)) > 0) { buf[n] = 0; buf[strlen(buf)-1] = '\0'; int i = 0; char* array[10]; char* token1 = strtok(buf, " "); char* newarray[10]; int exitIndicator = 0; char* directOut; char* directory; while ((token1 != NULL)) { array[i++] = token1; token1 = strtok(NULL, " "); }//while array[i] = NULL; for (int j = 0; j < i; j++) { if (!strcmp(array[j], "cd")) { directory = array[j+1]; int change = chdir(directory); exitIndicator = 1; } } printf("1730sh:~%s$ \n", directory); } }
问题根源
- 未初始化变量风险:
directory变量仅在执行cd命令时赋值,执行其他命令时该变量未初始化,属于未定义行为,导致显示异常。 - 目录获取方式错误:直接使用
cd的参数作为显示路径,无法处理相对路径(如cd ..)、符号链接等场景,且无法跟踪实际工作目录的变化。
修复方案
核心思路是每次输出提示符前,主动获取当前实际工作目录,并将家目录路径替换为~,模拟原生Shell的显示逻辑:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> #include <fcntl.h> #include <string.h> #define BUFFERSIZE 1024 #define PATH_MAX 4096 // 多数系统的路径最大长度 int main(int argc, char* argv[]) { char buf[BUFFERSIZE]; int n; char current_dir[PATH_MAX]; char* home_dir = getenv("HOME"); // 获取用户家目录 size_t home_len = home_dir ? strlen(home_dir) : 0; // 初始提示符 if (getcwd(current_dir, PATH_MAX) != NULL) { char prompt_path[PATH_MAX]; // 替换家目录为~ if (home_dir && strstr(current_dir, home_dir) == current_dir) { snprintf(prompt_path, PATH_MAX, "~%s", current_dir + home_len); } else { strcpy(prompt_path, current_dir); } printf("1730sh:%s$ ", prompt_path); } else { printf("1730sh:~$ "); // 获取失败时默认显示家目录 } while ((n = read(STDIN_FILENO, buf, BUFFERSIZE)) > 0) { buf[n] = 0; buf[strlen(buf)-1] = '\0'; int i = 0; char* array[10]; char* token1 = strtok(buf, " "); int exitIndicator = 0; while ((token1 != NULL)) { array[i++] = token1; token1 = strtok(NULL, " "); } array[i] = NULL; // 处理cd命令 if (i > 0 && !strcmp(array[0], "cd")) { char* target_dir = array[1] ? array[1] : home_dir; // 无参数时回到家目录 if (chdir(target_dir) == -1) { perror("cd"); } exitIndicator = 1; } // 处理其他外部命令(保留原逻辑,这里省略具体实现) if (!exitIndicator && i > 0) { pid_t pid = fork(); if (pid == 0) { execvp(array[0], array); perror("execvp"); exit(EXIT_FAILURE); } else if (pid > 0) { wait(NULL); } } // 生成新提示符 if (getcwd(current_dir, PATH_MAX) != NULL) { char prompt_path[PATH_MAX]; if (home_dir && strstr(current_dir, home_dir) == current_dir) { snprintf(prompt_path, PATH_MAX, "~%s", current_dir + home_len); } else { strcpy(prompt_path, current_dir); } printf("1730sh:%s$ ", prompt_path); } else { printf("1730sh:~$ "); } } return 0; }
关键修改点
- 使用
getcwd()主动获取当前工作目录,确保路径准确。 - 通过
getenv("HOME")获取家目录,将路径中匹配家目录的部分替换为~,符合原生Shell的显示习惯。 - 移除依赖
cd参数的逻辑,避免未初始化变量问题。 - 处理
cd无参数的场景(默认回到家目录),并添加错误提示。
内容的提问来源于stack exchange,提问作者sgrandom
相关产品推荐
相关产品推荐

