IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [原]Linux下文件移动问题的排查及解决(以C代码为例)

    zhouzxi发表于 2016-08-25 21:51:36
    love 0

    问题描述
    某软件具有的功能之一是将Linux下的某个源路径下的文件移动(剪切)到目的路径下。在软件运行之前,只有源路径可能是存在的,源路径下面没有子目录,只可能会有普通的文本文件。

    在软件运行起来之后,发现在Linux屏幕上经常出现如下信息:

    mv: cannot stat `/home/zhou/zhouzx/Test/FileMove/SrcDir/*’: No suchfile or directory

    程序源代码及问题分析
    我们查看了程序中实现该功能的源代码,如下所示:

    /**********************************************************************
    * 版权所有 (C)2016, Zhou Zhaoxiong
    *
    * 文件名称:FileMove.c
    * 文件标识:无
    * 内容摘要:示例两个目录之间文件的移动
    * 其它说明:无
    * 当前版本:V1.0
    * 作   者:ZhouZhaoxiong
    * 完成日期:20160825
    *
    **********************************************************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dirent.h>
    #include <unistd.h>
    
    
    // 重定义数据类型
    typedef signed   int        INT32;
    typedef unsigned int        UINT32;
    typedef unsigned char       UINT8;
    
    // 函数声明
    void MoveFileFromSrcToDest(UINT8 *pszSrcDir, UINT8*pszDestDir);
    
    
    /****************************************************************
    * 功能描述: 主函数
    * 输入参数: 无
    * 输出参数: 无
    * 返 回 值: 0-执行完成
    * 其他说明: 无
    * 修改日期         版本号       修改人         修改内容
    *-------------------------------------------------------------
    * 20160825       V1.0     Zhou Zhaoxiong     创建
    ****************************************************************/
    INT32 main(void)
    {
        UINT8 szSrcDir[100]  = {0};
        UINT8 szDestDir[100] = {0};
    
        // 获取源路径
        snprintf(szSrcDir,sizeof(szSrcDir)-1, "%s/zhouzx/Test/FileMove/SrcDir/",getenv("HOME"));
    
        // 获取目的路径
        snprintf(szDestDir,sizeof(szDestDir)-1, "%s/zhouzx/Test/FileMove/DestDir/",getenv("HOME"));
    
        // 执行文件的移动操作
       MoveFileFromSrcToDest(szSrcDir, szDestDir);
    
        return 0;
    }
    
    
    /****************************************************************
    * 功能描述: 将文件从源路径拷贝到目的路径
    * 输入参数: pszSrcDir-源路径
                pszDestDir-目的路径
    * 输出参数: 无
    * 返 回 值: 0-执行完成
    * 其他说明: 无
    * 修改日期        版本号        修改人         修改内容
    *-------------------------------------------------------------
    * 20160825       V1.0     Zhou Zhaoxiong     创建
    ****************************************************************/
    void MoveFileFromSrcToDest(UINT8 *pszSrcDir, UINT8*pszDestDir)
    {
        UINT32         iCountFlag    = 0;
        UINT8          szCmdbuf[100] = {0};
        DIR           *pDir          = NULL;
        struct dirent *pDirent       = NULL;
    
        if (pszSrcDir ==NULL || pszDestDir == NULL)
        {
           printf("MoveFileFromSrcToDest: pszSrcDir or pszDestDir isNULL!\n");
    
            return;
        }
    
        // 下面执行文件移动操作
        // 第一步判断源路径是否存在
        // 第二步创建目的路径
        // 第三步执行文件的移动操作
        if (0 == access(pszSrcDir, F_OK))   
        {
            // 创建目的路径
            memset(szCmdbuf,0x00, sizeof(szCmdbuf));
           snprintf(szCmdbuf, sizeof(szCmdbuf)-1, "mkdir -p %s",pszDestDir);
           system(szCmdbuf);
    
            // 移动源路径下所有文件
            memset(szCmdbuf,0x00, sizeof(szCmdbuf));
           snprintf(szCmdbuf, sizeof(szCmdbuf)-1,"mv %s* %s", pszSrcDir,pszDestDir);
    
           system(szCmdbuf);
        }
        else
        {
           printf("MoveFileFromSrcToDest: %s does not exist!\n",pszSrcDir);
        }
    }

    我们将该代码文件FileMove.c上传到Linux机器上,并使用“gcc -g -o FileMoveFileMove.c”命令对之进行编译,然后执行“FileMove”命令,运行结果如下:

    mv: cannot stat `/home/zhou/zhouzx/Test/FileMove/SrcDir/*’: No suchfile or directory

    可以看到,程序的运行结果和软件运行之后所出现的信息是一样的。

    分析源代码,可以发现,程序虽然判断了源路径是否存在,但未判断该路径下是否有文件。在没有文件存在的情况下执行mv操作,系统就会打出上面所示的提示信息。

    我们转到“/home/zhou/zhouzx/Test/FileMove/SrcDir/”路径下,发现该路径下确实没有文件存在。大家可以在该目录下手动执行一下mv命令,看是否会出现提示信息。

    代码修改及运行结果
    通过上面的分析,我们知道之前的程序还少了一道判断源路径下是否有文件存在的流程。修改之后的程序如下:

    /**********************************************************************
    * 版权所有 (C)2016, Zhou Zhaoxiong
    *
    * 文件名称:FileMove.c
    * 文件标识:无
    * 内容摘要:示例两个目录之间文件的移动
    * 其它说明:无
    * 当前版本:V1.0
    * 作   者:ZhouZhaoxiong
    * 完成日期:20160825
    *
    **********************************************************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dirent.h>
    #include <unistd.h>
    
    
    // 重定义数据类型
    typedef signed   int       INT32;
    typedef unsigned int       UINT32;
    typedef unsigned char      UINT8;
    
    // 函数声明
    void MoveFileFromSrcToDest(UINT8 *pszSrcDir, UINT8*pszDestDir);
    
    
    /****************************************************************
    * 功能描述: 主函数
    * 输入参数: 无
    * 输出参数: 无
    * 返 回 值: 0-执行完成
    * 其他说明: 无
    * 修改日期        版本号       修改人          修改内容
    *-------------------------------------------------------------
    * 20160825       V1.0     Zhou Zhaoxiong     创建
    ****************************************************************/
    INT32 main(void)
    {
        UINT8 szSrcDir[100]  = {0};
        UINT8 szDestDir[100] = {0};
    
        // 获取源路径
        snprintf(szSrcDir,sizeof(szSrcDir)-1, "%s/zhouzx/Test/FileMove/SrcDir/",getenv("HOME"));
    
        // 获取目的路径
        snprintf(szDestDir,sizeof(szDestDir)-1, "%s/zhouzx/Test/FileMove/DestDir/",getenv("HOME"));
    
        // 执行文件的移动操作
        MoveFileFromSrcToDest(szSrcDir, szDestDir);
    
        return 0;
    }
    
    
    /****************************************************************
    * 功能描述: 将文件从源路径拷贝到目的路径
    * 输入参数: pszSrcDir-源路径
                pszDestDir-目的路径
    * 输出参数: 无
    * 返 回 值: 0-执行完成
    * 其他说明: 无
    * 修改日期        版本号         修改人        修改内容
    * -------------------------------------------------------------
    * 20160825       V1.0     Zhou Zhaoxiong     创建
    ****************************************************************/
    void MoveFileFromSrcToDest(UINT8 *pszSrcDir, UINT8*pszDestDir)
    {
        UINT32         iCountFlag    = 0;
        UINT8          szCmdbuf[100] = {0};
        DIR           *pDir          = NULL;
        struct dirent *pDirent       = NULL;
    
        if (pszSrcDir ==NULL || pszDestDir == NULL)
        {
           printf("MoveFileFromSrcToDest: pszSrcDir or pszDestDir isNULL!\n");
    
            return;
        }
    
        // 下面执行文件移动操作
        // 第一步判断源路径是否存在
        // 第二步判断源路径下是否有文件存在
        // 第三步创建目的路径
        // 第四步执行文件的移动操作
        if (0 ==access(pszSrcDir, F_OK))   
        {
            if ((pDir =opendir(pszSrcDir)) == NULL)  // 打开源路径失败
            {
               printf("MoveFileFromSrcToDest: open %s failed!\n", pszSrcDir);
    
                return;
            }
    
            iCountFlag = 0;
            while ((pDirent= readdir(pDir)) != NULL)
            {
                if(strcmp(pDirent->d_name, ".") == 0 || strcmp(pDirent->d_name,"..") == 0)   // 表示当前目录或父目录
                {
                   continue;
                }
    
                iCountFlag++;  // 文件个数加1
            }
                  closedir(pDir);
    
            if (iCountFlag> 0)   // 源路径下有文件存在
            {
                // 创建目的路径
                memset(szCmdbuf, 0x00, sizeof(szCmdbuf));
               snprintf(szCmdbuf, sizeof(szCmdbuf)-1, "mkdir -p %s",pszDestDir);
               system(szCmdbuf);
    
                // 移动源路径下所有文件
               memset(szCmdbuf, 0x00, sizeof(szCmdbuf));
               snprintf(szCmdbuf, sizeof(szCmdbuf)-1,"mv %s* %s", pszSrcDir,pszDestDir);
    
               system(szCmdbuf);
    
               printf("MoveFileFromSrcToDest: moved %d file(s) from %s to%s!\n", iCountFlag, pszSrcDir, pszDestDir);
            }
            else
            {
               printf("MoveFileFromSrcToDest: no files in %s!\n", pszSrcDir);
            }
        }
        else
        {
           printf("MoveFileFromSrcToDest: %s does not exist!\n",pszSrcDir);
        }
    }

    我们将该程序编译之后,再来详细测试一下。

    1)当源路径不存在时,程序运行结果为:

    MoveFileFromSrcToDest:/home/zhou/zhouzx/Test/FileMove/SrcDir/ doesnot exist!

    2)当源路径存在但该路径下无文件时,程序运行结果为:

    MoveFileFromSrcToDest:no files in /home/zhou/zhouzx/Test/FileMove/SrcDir/!

    3)当源路径存在且该路径下有3个文件时,程序运行结果为:

    MoveFileFromSrcToDest:moved 3 file(s) from /home/zhou/zhouzx/Test/FileMove/SrcDir/to /home/zhou/zhouzx/Test/FileMove/DestDir/!

    可以看到,现在程序的功能正常了。

    总结
    在实际的软件开发项目中,我们在编写程序的时候,要考虑到方方面面的情况,特别是某些异常情况。就像本文中描述的问题这样,也许在正常情况下,源路径下面是有文件的,也许源路径下面无文件的概率很小,但我们在程序中要考虑到这种情况。考虑问题是否全面,这也是判断一个开发人员是否优秀的标准。



沪ICP备19023445号-2号
友情链接