¿Cómo puedo obtener el comando sí para forzar la sobrescritura y hacerlo con nuevas líneas?

¿Cómo puedo obtener el comando sí para forzar la sobrescritura y hacerlo con nuevas líneas?

Me gustaría cpavisar antes de sobrescribir, así que estoy usando -i.

(A veces puedo usar un alias para cp, o similar, por lo que cpsiempre ocurre con -i).

Quizás quiera decir sobrescribir todo. Sé que es el valor predeterminado, pero desde que lo uso -ino lo veo.

Quiero poder hacer que diga 'sí' a todos o 'no' a todos fácilmente.

No estoy preguntando cómo omitir un alias, quiero el archivo -i.

Aquí está mi intento de forzar que sí, dado -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$ 

Entonces me las arreglo para forzar 'y' a todos pero luego no obtengo nuevas líneas.

Cuando lo intento yes ''| , no envía un sí.

También me gustaría poder aprobar un 'n'/'no'.

Y es posible que tenga muchos archivos, por lo que no busco escribir manualmente yEntero nEnterpara cada archivo.

No me importa una solución que no implique el yescomando.

Respuesta1

Esto no es tan fácil como parece.

Análisis

Al ejecutar cp -iy responder solicitudes de forma interactiva, la nueva línea que obtiene después de escribir yEnterproviene de la disciplina de línea. La disciplina de línea hace eco yy la nueva línea.

Puede observar este mecanismo ejecutando sole caten una terminal. Cuando catespera entrada, puede escribir una línea larga e incluso borrar caracteres (con Backspace) o toda la línea (con Ctrl+ u); Todo lo que ves es manejado por la disciplina de línea, catsimplemente se queda ahí sin ninguna intervención. Solo cuando presionas Enter(o Ctrl+ m, o Ctrl+ j), catobtiene la línea y la imprime. La nueva línea después de lo que escribió proviene de la disciplina de línea, la nueva línea después de lo catimpreso proviene de cat.

O puede escribir algo y presionar Ctrl+ dpara enviarlo catsin una nueva línea. Entonces no habrá nueva línea después de lo que escribió ni ninguna nueva línea después de lo que catimprimió.

De manera similar, cuando se lo solicite cp -i, puede escribir interactivamente yCtrl+ dCtrl+ d(¿por qué dos veces?aquí), cpaceptará yy verá yla disciplina de línea repetida, pero sin nueva línea (porque no escribió ninguna). cpen sí mismo no imprime una nueva línea aquí. Normalmente (es decir, cuando escribe Enter) lo que ve se ve bien (es decir, con nuevas líneas en los lugares correctos) debido a la disciplina de línea. Podemos decir que cpespera una disciplina de línea que inyecte caracteres de nueva línea cuando corresponda y, por lo tanto, haga que el resultado se vea bien.

La cuestión eshayUna disciplina de línea entre su teclado y cp -i, hace eco de lo que escribe, incluida una nueva línea en Enter.

En su yes | cp -i …, cprecibe entrada casi como si hubiera escrito yEntera través de una disciplina de línea, pero esta vez no hay nada como una disciplina de línea que haga eco de lo que ingresa cp. Esta es la razón por la que no observaste nuevas líneas (ni ycaracteres).

En el caso de yes '' | cp -i …, las nuevas líneas posteriores not overwrittenen realidad fueron impresas por cp. Lo que falta es una nueva línea antes de cada not overwritten. Sin yes, si simplemente presiona Enteren respuesta al mensaje, lo verá not overwrittenen una línea separada.


Hacia la solución

Para obtener lo que desea, necesita algo que refleje la entrada que ingresa cp. A primera vista parece que puede ser una disciplina lineal real (algunas ideas aquí:Cómo engañar a un comando haciéndole creer que su salida va a una terminal; tenga en cuenta que no queremos engañar cp, queremos un "efecto secundario" de tener una terminal) o teeentre yesy cp, así:

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

Lo anterior no funcionará bien porque yesgenera su salida inmediatamente y, en la medida de lo posible, es como un usuario que tritura yEntersin importar si se le solicita o no. Hacer eco de esto hace que el resultado parezca mucho peor que lo que publicó en la pregunta.

Incluso si supiera de antemano que necesita solo uno yEnter, usar echo yen lugar de yestampoco funcionaría bien, porque lo más probable es que la entrada se vea e imprima (mediante la disciplina de línea agregada o mediante tee) antes de que cpse imprima su mensaje.


Solución

Una solución adecuada es ejecutar cp -i …con pty adicional, pero solo proporcione información cuando se le solicite. expect(1)lo puede hacer. Este es un script rápido y sucio 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
   }
}

Los usuarios con localizado cpdeben ajustar el "overwrite *\\?"patrón.

Tenga en cuenta que tengo poca experiencia con expect, el guión puede no ser óptimo o incluso algo defectuoso. Trátelo como una prueba de concepto. Guarde el script como cpxen un directorio de su $PATH, hágalo ejecutable ( chmod +x cpx) y utilícelo así:

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

En la práctica, puede ser bueno definir alias de shell:

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

y usarlos así:

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

Respuesta2

Muchas formas de omitir el alias para usar nativo cp:

  • Utilice el comando incorporado:command cp
  • Utilice la ruta completa del comando:/bin/cp
  • Agregue un \ en cualquier parte del nombre del comando, por ejemplo:\cp
  • Cite el comando: "cp"o'cp'

Respuesta3

Puedes usar 'sí |' delante de su código.

yes | cp -i ?.? smalls

información relacionada