Me gustaría cp
avisar antes de sobrescribir, así que estoy usando -i
.
(A veces puedo usar un alias para cp
, o similar, por lo que cp
siempre ocurre con -i
).
Quizás quiera decir sobrescribir todo. Sé que es el valor predeterminado, pero desde que lo uso -i
no 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 yes
comando.
Respuesta1
Esto no es tan fácil como parece.
Análisis
Al ejecutar cp -i
y 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 y
y la nueva línea.
Puede observar este mecanismo ejecutando sole cat
en una terminal. Cuando cat
espera 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, cat
simplemente se queda ahí sin ninguna intervención. Solo cuando presionas Enter(o Ctrl+ m, o Ctrl+ j), cat
obtiene 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 cat
impreso proviene de cat
.
O puede escribir algo y presionar Ctrl+ dpara enviarlo cat
sin 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 cat
imprimió.
De manera similar, cuando se lo solicite cp -i
, puede escribir interactivamente yCtrl+ dCtrl+ d(¿por qué dos veces?aquí), cp
aceptará y
y verá y
la disciplina de línea repetida, pero sin nueva línea (porque no escribió ninguna). cp
en 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 cp
espera 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 …
, cp
recibe 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 y
caracteres).
En el caso de yes '' | cp -i …
, las nuevas líneas posteriores not overwritten
en 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 overwritten
en 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 tee
entre yes
y cp
, así:
# both flawed
yes | socat STDIO EXEC:'cp -i …',pty
yes | tee >/dev/tty | cp -i …
Lo anterior no funcionará bien porque yes
genera 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 y
en lugar de yes
tampoco 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 cp
se 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 cp
deben 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 cpx
en 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