如何用C语言编写我自己的mv(rename / move)unix命令版本?

时间:2016-07-17 22:01:17

标签: c linux unix

我想为move(mv)Unix命令编写自己的代码。我是C语言的新手,显然在如何修复我的代码上丢失了。如果两个输入都是文件名,我想执行重命名文件等操作。如果dest_folder是一个目录,我想将文件移动到目录中。

但我无法修复特定问题的代码,因为我对目录和C不太熟悉。该程序需要2个输入源和目标,然后执行必要的功能。我显然能够重命名我的文件,但我无法将文件移动到特定文件夹由于某种原因我不知道?

需要有关将文件移动到特定目录的帮助。

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.6.RELEASE</version>
</parent>

2 个答案:

答案 0 :(得分:1)

如您所知,mv是通过重命名实现的。 rename是一个原子系统调用,可以将文件重命名为文件,将emtpy目录重命名为空目录或目录的目录(dest必须为nonentity)。因此有以下情况需要处理:

  1. mv file1 file2 - 使用重命名功能

  2. mv dir1 dir2(无效或空) - 使用重命名功能

  3. mv dir1 dir2(非空) - 将dir1重命名为dir2 / dir1

  4. mv file dir(exists) - 将文件重命名为dir / file

  5. mv dir文件 - 非法操作

  6. 你明白了吗?

答案 1 :(得分:0)

rename(3)无法按照您希望的方式运作(我不知道为什么,请问委员会)。你无法做rename(some_file, some_directory),就像man-page所说的那样。

只需使用stat(2)(或lstat(2),如有必要)并检查您获得了什么。这是一个简短的,可运行的草图。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>

    // check if it is the same inode on the same device
#define SAME_INODE(a, b) ((a).st_ino == (b).st_ino && (a).st_dev == (b).st_dev)

    // ALL CHECKS OMMITTED!

int main(int argc, char **argv)
{

  struct stat statbuf_src, statbuf_dest;
  char *src, *dest, *new_src, *new_dest;
  char *current_directory;

  if (argc != 3) {
    fprintf(stderr, "usage: %s src dest\n", argv[0]);
    exit(EXIT_FAILURE);
  }
  // work on copy
  src = malloc(strlen(argv[1]) + 1);
  dest = malloc(strlen(argv[2]) + 1);
  strcpy(src, argv[1]);
  strcpy(dest, argv[2]);

  stat(src, &statbuf_src);
  stat(dest, &statbuf_dest);

  // there are many more, of course
  printf("\"%s\" is a ", src);
  if (S_ISREG(statbuf_src.st_mode)) {
    puts("a regular file");
  }
  if (S_ISDIR(statbuf_src.st_mode)) {
    puts("a directory");
  }

  printf("\"%s\" is a ", dest);
  if (S_ISREG(statbuf_dest.st_mode)) {
    puts("a regular file");
  }
  if (S_ISDIR(statbuf_dest.st_mode)) {
    puts("a directory");
  }

  if (SAME_INODE(statbuf_dest, statbuf_src)) {
    printf("%s and %s are the identical\n", src, dest);
  }
  // if that is not set you have to do it by hand:
  // climb up the tree, concatenating names until the inodes are the same
  current_directory = getenv("PWD");
  printf("current directory is \"%s\"\n", current_directory);

  // I'm pretty sure it can be done in a much more elegant way
  new_src = malloc(strlen(src) + 1 + strlen(current_directory) + 1);
  strcpy(new_src,current_directory);
  strcat(new_src,"/");
  strcat(new_src,src);
  printf("new_src = %s\n",new_src);

  new_dest = malloc(strlen(dest) + 1 + strlen(current_directory) + 1 + strlen(src) + 1);
  strcpy(new_dest,current_directory);
  strcat(new_dest,"/");
  strcat(new_dest,dest);
  strcat(new_dest,"/");
  strcat(new_dest,src);
  printf("new_dest = %s\n",new_dest);

  if(rename(new_src,new_dest) != 0){
    fprintf(stderr,"rename failed with error %s\n",strerror(errno));
  }

  free(new_src);
  free(new_dest);
  free(src);
  free(dest);

  exit(EXIT_SUCCESS);
}

修改:为下面的解释添加了代码 最后你有一个你所在的路径,如果给出的参数是目录或常规文件和路径的信息。如果源是常规文件而目标是目录,则将路径连接到常规文件的名称,带有目录名称的路径和常规文件的名称(源)

出于

Path = /home/foo
src = bar
dest = coffee

构建

new_src = /home/foo/bar
new_dest = /home/foo/coffee/bar

这样对rename()的调用是

rename(new_src, new_dest);

这样您就可以将常规文件重命名为rename()接受的常规文件。

请注意,rename()每个文件系统中都不起作用,但大多数都是。