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

简介: 问题描述 某软件具有的功能之一是将Linux下的某个源路径下的文件移动(剪切)到目的路径下。

问题描述
某软件具有的功能之一是将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/!

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

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

目录
相关文章
|
2月前
|
Linux 数据安全/隐私保护 Windows
命令方式:window向linux传文件
【10月更文挑战第6天】本文介绍了如何在Linux系统中通过命令`ip a`获取IP地址,并在Windows系统下使用CMD命令行工具和SCP命令实现文件传输。示例展示了如何将D盘中的`mm.jar`文件上传至IP地址为192.168.163.122的Linux系统的/up/目录下,最后在Linux系统中确认文件传输结果。
255 65
|
2月前
|
运维 安全 Linux
Linux中传输文件文件夹的10个scp命令
【10月更文挑战第18天】本文详细介绍了10种利用scp命令在Linux系统中进行文件传输的方法,涵盖基础文件传输、使用密钥认证、复制整个目录、从远程主机复制文件、同时传输多个文件和目录、保持文件权限、跨多台远程主机传输、指定端口及显示传输进度等场景,旨在帮助用户在不同情况下高效安全地完成文件传输任务。
298 5
|
2月前
|
Linux Shell 数据库
Linux文件查找新姿势:总有一种你没见过
【10月更文挑战第18天】文件查找是Linux用户提升工作效率的重要技能。本文介绍了几种实用的文件查找方法,包括基础的`find`命令、快速的`locate`和`mlocate`、高效的`fd`工具、以及结合`grep`和`rg`进行内容搜索。此外,还提供了编写Shell脚本和使用图形界面工具的建议,帮助你更灵活地管理文件。
77 3
|
27天前
|
Linux 开发工具 Perl
在Linux中,有一个文件,如何删除包含“www“字样的字符?
在Linux中,如果你想删除一个文件中包含特定字样(如“www”)的所有字符或行,你可以使用多种文本处理工具来实现。以下是一些常见的方法:
40 5
|
27天前
|
安全 Linux 数据安全/隐私保护
在 Linux 系统中,查找文件所有者是系统管理和安全审计的重要技能。
在 Linux 系统中,查找文件所有者是系统管理和安全审计的重要技能。本文介绍了使用 `ls -l` 和 `stat` 命令查找文件所有者的基本方法,以及通过文件路径、通配符和结合其他命令的高级技巧。还提供了实际案例分析和注意事项,帮助读者更好地掌握这一操作。
44 6
|
27天前
|
Linux
在 Linux 系统中,`find` 命令是一个强大的文件查找工具
在 Linux 系统中,`find` 命令是一个强大的文件查找工具。本文详细介绍了 `find` 命令的基本语法、常用选项和具体应用示例,帮助用户快速掌握如何根据文件名、类型、大小、修改时间等条件查找文件,并展示了如何结合逻辑运算符、正则表达式和排除特定目录等高级用法。
66 6
|
28天前
|
监控 Linux Perl
Linux 命令小技巧:显示文件指定行的内容
在 Linux 系统中,处理文本文件是一项常见任务。本文介绍了如何使用 head、tail、sed 和 awk 等命令快速显示文件中的指定行内容,帮助你高效处理文本文件。通过实际应用场景和案例分析,展示了这些命令在代码审查、日志分析和文本处理中的具体用途。同时,还提供了注意事项和技巧,帮助你更好地掌握这些命令。
41 4
|
1月前
|
网络协议 Linux
linux系统重要文件目录
本文介绍了Linux系统中的重要目录及其历史背景,包括根目录、/usr、/etc、/var/log和/proc等目录的结构和功能。其中,/etc目录下包含了许多关键配置文件,如网卡配置、DNS解析、主机名设置等。文章还详细解释了各目录和文件的作用,帮助读者更好地理解和管理Linux系统。
55 2
|
2月前
|
Linux 开发工具 数据安全/隐私保护
linux异常一:feng 不在 sudoers 文件中,此事将被报告。yum提示Another app is currently holding the yum lock; waiting for
这篇文章介绍了在CentOS 7系统中安装Docker时遇到的两个常见问题及其解决方法:用户不在sudoers文件中导致权限不足,以及yum被锁定的问题。
42 2
linux异常一:feng 不在 sudoers 文件中,此事将被报告。yum提示Another app is currently holding the yum lock; waiting for
|
1月前
|
缓存 监控 Linux