wie kann ich mit dem Yes-Befehl das Überschreiben erzwingen und dies mit neuen Zeilen tun?

wie kann ich mit dem Yes-Befehl das Überschreiben erzwingen und dies mit neuen Zeilen tun?

Ich möchte cpvor dem Überschreiben eine Bestätigung erhalten, daher verwende ich -i.

(Ich verwende manchmal einen Alias ​​für cpoder ähnliches, sodass cpes immer mit auftritt -i.)

Ich möchte vielleicht „Alles überschreiben“ sagen. Ich weiß, dass das die Standardeinstellung ist, aber da ich verwende, -isehe ich das nicht.

Ich möchte problemlos die Antwort „Ja“ auf alle oder „Nein“ auf alle erhalten.

Ich frage nicht, wie man einen Alias ​​umgeht, ich möchte das -i.

Hier ist mein Versuch, ein „Ja“ zu erzwingen -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$ 

Ich schaffe es also, überall ein „y“ zu erzwingen, aber dann bekomme ich keine neuen Zeilen.

Wenn ich yes ''| es versuche, wird kein „Ja“ gesendet.

Ich möchte auch ein „n“/„nein“ übergeben können.

Und da ich möglicherweise viele Dateien habe, möchte ich nicht jede Datei yEntereinzeln manuell eingeben.nEnter

Ich habe nichts gegen eine Lösung, die den Befehl nicht beinhaltet yes.

Antwort1

Dies ist nicht so einfach, wie es scheint.

Analyse

Beim Ausführen cp -iund Beantworten von Eingabeaufforderungen interaktiv yEnterstammt die neue Zeile, die Sie nach dem Eintippen erhalten, aus der Zeilendisziplin. Die Zeilendisziplin wird als Echo yund als neue Zeile ausgegeben.

Sie können diesen Mechanismus beobachten, indem Sie sole catin einem Terminal ausführen. Wenn catauf eine Eingabe gewartet wird, können Sie eine lange Zeile eingeben und sogar Zeichen (mit Backspace) oder die ganze Zeile (mit Ctrl+ u) löschen; alles, was Sie sehen, wird von der Zeilendisziplin verarbeitet und catbleibt einfach ohne Eingabe stehen. Nur wenn Sie Enter(oder Ctrl+ m, oder Ctrl+ j) drücken, catwird die Zeile abgerufen und gedruckt. Die neue Zeile nach dem, was Sie eingegeben haben, stammt aus der Zeilendisziplin, die neue Zeile nach dem, was catgedruckt wurde, stammt aus cat.

Oder Sie können etwas eingeben und Ctrl+ drücken d, um es ohne Zeilenumbruch zu senden cat. Dann gibt es nach dem Eingegebenen und nach dem catAusdrucken keinen Zeilenumbruch.

Ebenso cp -ikönnen Sie, wenn Sie dazu aufgefordert werden, interaktiv yCtrl+ dCtrl+ eingeben d(warum zweimal?Hier), cpwird akzeptiert yund Sie sehen yeine Wiederholung durch die Zeilendisziplin, aber keinen Zeilenumbruch (weil Sie keinen eingegeben haben). cpselbst druckt hier keinen Zeilenumbruch. Normalerweise (d. h. wenn Sie eingeben Enter) sieht das, was Sie sehen, aufgrund der Zeilendisziplin richtig aus (d. h. mit Zeilenumbrüchen an den richtigen Stellen). Wir können sagen, dass cpeine Zeilendisziplin erwartet wird, die Zeilenumbruchzeichen an den geeigneten Stellen einfügt und so dafür sorgt, dass die Ausgabe gut aussieht.

Der Punkt istEs gibteine Zeilendisziplin zwischen Ihrer Tastatur und cp -i. Es gibt wieder, was Sie eingeben, einschließlich einer neuen Zeile bei Enter.

In Ihrem yes | cp -i …erhält cpEingaben fast so, als ob Sie yEnterüber eine Zeilendisziplin eingegeben hätten, aber dieses Mal gibt es nichts wie eine Zeilendisziplin, die das, was eingegeben wird, wiedergeben würde cp. Aus diesem Grund haben Sie keine Zeilenumbrüche (und keine yZeichen) beobachtet.

Im Fall von wurden yes '' | cp -i …die Zeilenumbrüche nach not overwrittentatsächlich von gedruckt cp. Was fehlt, ist ein Zeilenumbruch vor jedem not overwritten. Ohne würden Sie in einer separaten Zeile sehen, yeswenn Sie einfach Enterals Antwort auf die Eingabeaufforderung drücken würden.not overwritten


Auf dem Weg zur Lösung

Um das gewünschte Ergebnis zu erzielen, benötigen Sie etwas, das die Eingaben widerspiegelt, die in eingehen cp. Auf den ersten Blick scheint es sich um eine echte Liniendisziplin zu handeln (hier ein paar Ideen:Wie man einen Befehl dazu bringt zu glauben, dass seine Ausgabe an ein Terminal geht; beachten Sie, dass wir nicht austricksen möchten cp, sondern einen „Nebeneffekt“ des Vorhandenseins eines Terminals erzielen möchten) oder teezwischen yesund cp, wie folgt:

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

Das Obige wird nicht gut funktionieren, da yesdie Ausgabe sofort und so weit wie möglich generiert wird. Es ist wie bei einem Benutzer, der hämmert, yEnteregal ob er dazu aufgefordert wird oder nicht. Wenn man dies wiederholt, sieht die Ausgabe viel schlechter aus als das, was Sie in der Frage gepostet haben.

Auch wenn Sie im Voraus wüssten, dass Sie nur ein benötigen yEnter, würde die Verwendung echo yvon anstelle von yesnicht gut funktionieren, da die Eingabe höchstwahrscheinlich gesehen und gedruckt würde (durch die hinzugefügte Zeile „disciple“ oder durch tee), bevor cpdie Eingabeaufforderung gedruckt wird.


Lösung

cp -i …Eine gute Lösung besteht darin , mit zusätzlichem PTY zu arbeiten , aber nur dann Eingaben zu machen, wenn man dazu aufgefordert wird. expect(1)kann das machen. Dies ist ein schnelles und einfaches expectSkript:

#!/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
   }
}

Benutzer mit lokalisierter Version cpsollten das Muster anpassen "overwrite *\\?".

Beachten Sie, dass ich wenig Erfahrung mit habe expect, das Skript ist möglicherweise nicht optimal oder sogar fehlerhaft. Betrachten Sie es als Proof of Concept. Speichern Sie das Skript als cpxin einem Verzeichnis in Ihrem $PATH, machen Sie es ausführbar ( chmod +x cpx) und verwenden Sie es wie folgt:

cpx y ?.? smalls
# or
cpx n ?.? smalls

In der Praxis kann es sinnvoll sein, Shell-Aliase zu definieren:

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

und verwenden Sie sie wie folgt:

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

Antwort2

Es gibt viele Möglichkeiten, den Alias ​​zu umgehen und native zu verwenden cp:

  • Verwenden Sie den integrierten Befehl:command cp
  • Verwenden Sie den vollständigen Pfad des Befehls:/bin/cp
  • Fügen Sie an beliebiger Stelle im Befehlsnamen ein \ hinzu, zum Beispiel:\cp
  • Zitieren Sie den Befehl: "cp"oder'cp'

Antwort3

Sie können vor Ihrem Code „yes |“ verwenden.

yes | cp -i ?.? smalls

verwandte Informationen