You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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);
    }
}

问题根源

  1. 未初始化变量风险:directory变量仅在执行cd命令时赋值,执行其他命令时该变量未初始化,属于未定义行为,导致显示异常。
  2. 目录获取方式错误:直接使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 21:55:24