我想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 | cp -i ?.? smalls