交互式复制文件:“cp:覆盖”

交互式复制文件:“cp:覆盖”

我试图找出-i交互式选项cp接受哪些单词作为输入。

为了您的方便,下面是设置用于实验的文件的代码。

touch example_file{1..3}
mkdir example_dir
cp example_file? example_dir
cp -i example_file? example_dir

然后 shell 以交互方式询问每个文件是否应该被覆盖。它似乎接受各种随机输入。

cp: overwrite 'example_dir/example_file1'? q
cp: overwrite 'example_dir/example_file2'? w
cp: overwrite 'example_dir/example_file3'? e

我尝试调查的源代码cp,但我不懂C,搜索也overwrite没有帮助。

据我所知,它接受一些单词作为覆盖的确认,而其他一切都被视为否。问题是,甚至像这样的词ys似乎也被接受为yes,所以我不知道什么有效,什么无效。

我想知道它到底是如何工作的,并通过文档或方法来证明它易懂的源代码片段。

答案1

POSIX 标准-i仅指定响应需要是“肯定”才能在生效时执行复制。

对于 GNU cp,此时的实际输入由名为 的函数处理yesno()。该函数定义在lib/yesno.cgnulib 源分发版中的文件,如下所示:

bool
yesno (void)
{
  bool yes;

#if ENABLE_NLS
  char *response = NULL;
  size_t response_size = 0;
  ssize_t response_len = getline (&response, &response_size, stdin);

  if (response_len <= 0)
    yes = false;
  else
    {
      /* Remove EOL if present as that's not part of the matched response,
         and not matched by $ for example.  */
      if (response[response_len - 1] == '\n')
        response[response_len - 1] = '\0';
      yes = (0 < rpmatch (response));
    }

  free (response);
#else
  /* Test against "^[yY]", hardcoded to avoid requiring getline,
     regex, and rpmatch.  */
  int c = getchar ();
  yes = (c == 'y' || c == 'Y');
  while (c != '\n' && c != EOF)
    c = getchar ();
#endif

  return yes;
}

如果 NLS(“国家语言支持”)是不是使用后,您可以看到该函数返回的唯一回复真的for 是以大写或小写字符开头的响应Y。任何附加或其他输入都将被丢弃。

如果NLS使用时,调用该rpmatch()函数来确定响应是否是肯定的。 NLS 库函数的目的rpmatch()是确定给定字符串是否是肯定的(支持国际化)。

在 BSD 系统上,相应的函数位于src/bin/cp/utils.c:

/*
 * If the file exists and we're interactive, verify with the user.
 */
int
copy_overwrite(void)
{
        int ch, checkch;

        if (iflag) {
                (void)fprintf(stderr, "overwrite %s? ", to.p_path);
                checkch = ch = getchar();
                while (ch != '\n' && ch != EOF)
                        ch = getchar();
                if (checkch != 'y' && checkch != 'Y')
                        return (0);
        }
        return 1;
}

这本质上与 GNU 代码中的非 NLS 代码路径相同。

答案2

如果您查看源代码并搜索,interactive您可以看到它设置了x.interactive = I_ASK_USER;,因此您可以在此文件和其他文件中搜索I_ASK_USER已检查的位置。

您会在copy.c函数调用附近找到此符号overwrite_ok,并且此函数包含对函数的调用yesno

其余的留给读者作为练习。 ;-)

相关内容