yes コマンドを使用して強制的に上書きし、新しい行で上書きするにはどうすればよいでしょうか?

yes コマンドを使用して強制的に上書きし、新しい行で上書きするにはどうすればよいでしょうか?

上書きする前に確認したいcpので を使用しています-i

( などの別名を使用することがあるためcp、 はcp常に とともに表示されます-i)。

すべて上書きするといいかもしれません。それがデフォルトであることは知っていますが、使用中なので-iそれが表示されません。

すべてに対して「はい」、またはすべてに対して「いいえ」を簡単に実行できるようにしたいです。

エイリアスをバイパスする方法を尋ねているのではなく、 を知りたいのです-i

ここでは、 を前提として、 yes を強制する試みを示します-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で送信することもできます。その場合、入力した内容の後に改行はなく、印刷された内容の後に改行はありません。catcat

同様に、 のプロンプトが表示されたら、対話的に+ +cp -iと入力できます(なぜ 2 回?yCtrldCtrldここ)cpは受け入れyy行規則によってエコーされたものが表示されますが、改行は表示されません (改行を入力しなかったため)。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の間に次のように記述します。yescp

# both flawed
yes | socat STDIO EXEC:'cp -i …',pty
yes | tee >/dev/tty | cp -i …

上記は、出力を即座に生成するため、うまく機能しません。プロンプトのyes有無に関係なく、ユーザーが入力を繰り返すようなものですyEnter。これをエコーすると、出力は質問に投稿したものよりもはるかに悪くなります。

たとえ 1 つの だけが必要であることが事前にわかっていたとしてもyEnterecho yの代わりにを使用してyesもうまく機能しません。これは、 がプロンプトを出力する前に、入力が(追加された行規則または によってtee)確認され、出力される可能性が高いためですcp


解決

適切な解決策は、cp -i …追加の pty を使用して実行し、プロンプトが表示されたときにのみ入力することです。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

実際には、シェルのエイリアスを定義すると良いでしょう。

alias cpy='cpx y'
alias cpn='cpx n'

次のように使用します。

cpy ?.? smalls
# or
cpn ?.? smalls

答え2

エイリアスをバイパスしてネイティブを使用する方法はたくさんありますcp

  • 組み込みコマンドを使用します:command cp
  • コマンドのフルパスを使用します:/bin/cp
  • コマンド名の任意の場所に \ を追加します。例:\cp
  • コマンドを引用:"cp"または'cp'

答え3

コードの前に「yes |」を使用できます。

yes | cp -i ?.? smalls

関連情報