我试图找出-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.c
gnulib 源分发版中的文件,如下所示:
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
。
其余的留给读者作为练习。 ;-)