如何獲得 yes 命令來強制覆蓋並使用新行執行此操作?

如何獲得 yes 命令來強制覆蓋並使用新行執行此操作?

我想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”。

我可能有很多文件,所以我不想手動鍵入yEnternEnter為每個文件。

我不介意不涉及命令的解決方案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++ dCtrld為什麼兩次?這裡),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 | cp -i ?.? smalls

相關內容