我想cp
在覆盖之前提示,因此我使用-i
。
cp
(我有时可能会使用或类似的别名,因此cp
总是与 一起出现-i
)。
我可能想说覆盖全部。我知道这是默认设置,但由于我正在使用,所以-i
我看不到它。
我希望能够轻松地让它对所有答案都回答“是”,或者对所有答案都回答“否”。
我不是问如何绕过别名,我想要-i
。
这是我在给定 的情况下强制“是”的尝试-i
。
~$ mkdir test1
~$ cd test1
~/test1$ mkdir smalls
~/test1$ touch a.a
~/test1$ touch b.b
~/test1$ cp -i ?.? smalls
~/test1$ cp -i ?.? smalls
overwrite smalls/a.a? (y/n [n]) y
overwrite smalls/b.b? (y/n [n]) y
~/test1$ yes|cp -i ?.? smalls
overwrite smalls/a.a? (y/n [n]) overwrite smalls/b.b? (y/n [n]) ~/test1$
~/test1$
~/test1$ yes ''|cp -i ?.? smalls
overwrite smalls/a.a? (y/n [n]) not overwritten
overwrite smalls/b.b? (y/n [n]) not overwritten
~/test1$
因此,我设法将“y”强制应用于所有内容,但却没有得到新行。
当我尝试yes ''|
时,它并没有发送“是”的答复。
我也希望能够传递“n”/“no”。
而且我可能有很多文件,所以我不想手动输入yEnter或nEnter输入每个文件。
我不介意不涉及命令的解决方案yes
。
答案1
这并不像看上去那么容易。
分析
运行cp -i
并回答时,它会以交互方式提示,输入后得到的换行符yEnter来自行规。行规会回显y
并显示换行符。
cat
您可以通过在终端中运行 sole 来观察此机制。当cat
等待输入时,您可以输入一长行,甚至可以删除字符(使用Backspace)或整行(使用Ctrl+ u);您看到的所有内容都由行规程处理,cat
只是停留在那里而没有任何输入。只有当您按下Enter(或Ctrl+ m,或Ctrl+ j)时,cat
才会获取该行并打印它。您输入的内容后的换行符来自行规程,cat
打印内容后的换行符来自cat
。
或者您可以输入一些内容,然后按Ctrl+d将其发送到cat
而不换行。这样,您输入的内容后就不会有换行符,cat
打印的内容后也不会有换行符。
类似地,当出现提示时cp -i
,您可以交互地输入yCtrl++ dCtrl(d为什么是两次?这里)cp
将接受y
,您将看到y
行规程的回显,但没有换行符(因为您没有输入换行符)。cp
本身不会在此处打印换行符。通常(即当您输入时Enter)您看到的内容看起来是正确的(即在正确的位置有换行符),这是因为行规程。我们可以说cp
期望行规程在适当的位置插入换行符,从而使输出看起来不错。
重点是有键盘和 之间的换行符cp -i
,它会响应您输入的内容,包括 上的换行符Enter。
在您的 中yes | cp -i …
,cp
输入几乎就像您yEnter通过行规则输入一样,但这次没有像行规则那样可以回显输入的内容。这就是您没有观察到换行符(也没有字符)cp
的原因。y
在 的情况下yes '' | cp -i …
, 之后的换行符not overwritten
实际上是由 打印的cp
。缺少的是每个 之前的换行符not overwritten
。如果没有yes
,如果您只是Enter响应提示而点击 ,您将not overwritten
在单独的行中看到。
走向解决方案
为了得到你想要的东西,你需要一些东西来回应输入的内容cp
。乍一看,它似乎可能是一个真正的生产线纪律(这里有一些想法:如何欺骗命令,让其认为其输出将发送到终端;请注意,我们不想欺骗cp
,我们想要一个拥有终端的“副作用”)或tee
在yes
和之间cp
,如下所示:
# both flawed
yes | socat STDIO EXEC:'cp -i …',pty
yes | tee >/dev/tty | cp -i …
上面的方法效果不佳,因为yes
它会立即生成尽可能多的输出,就像一个用户yEnter不管是否提示都会乱七八糟一样。回显此方法会使输出看起来比您在问题中发布的内容更糟糕。
即使您事先知道只需要一个yEnter,使用echo y
而不是也不会很好地工作,因为在打印其提示之前yes
,输入很可能会被看到并打印(通过添加的行规则或tee
) 。cp
解决方案
一个合适的解决方案是使用额外的 pty 运行cp -i …
,但只在提示时给它输入。expect(1)
可以做到。这是一个快速而肮脏的expect
脚本:
#!/usr/bin/expect -f
set str [lindex $argv 0]
spawn -noecho cp -i {*}[lrange "$argv" 1 end]
while 1 {
expect {
"overwrite *\\?" { send "$str\r" }
eof exit
}
}
有本地化需求的用户cp
请自行调整"overwrite *\\?"
模式。
请注意,我对 经验不足expect
,该脚本可能不是最理想的,甚至有些缺陷。将其视为概念证明。将脚本保存为cpx
目录中的$PATH
,使其可执行(chmod +x cpx
)并按如下方式使用:
cpx y ?.? smalls
# or
cpx n ?.? smalls
在实践中,定义 shell 别名可能会很好:
alias cpy='cpx y'
alias cpn='cpx n'
并像这样使用它们:
cpy ?.? smalls
# or
cpn ?.? smalls
答案2
有很多方法可以绕过别名来使用 native cp
:
- 使用内置命令:
command cp
- 使用命令的完整路径:
/bin/cp
- 在命令名称的任何位置添加 \,例如:
\cp
- 引用命令:
"cp"
或'cp'
答案3
您可以在代码前使用“yes |”。
yes | cp -i ?.? smalls