como posso obter o comando sim para forçar a substituição e fazê-lo com novas linhas?

como posso obter o comando sim para forçar a substituição e fazê-lo com novas linhas?

Gostaria cpde avisar antes de substituir, então estou usando o -i.

(Às vezes posso usar um alias para cp, ou similar, então cpsempre ocorre com -i).

Posso querer dizer sobrescrever tudo. Eu sei que esse é o padrão, mas como estou usando, -inão vejo isso.

Quero ser capaz de fazer com que seja fácil dizer 'sim' para todos ou 'não' para todos.

Não estou perguntando como ignorar um alias, quero o arquivo -i.

Aqui está minha tentativa de forçar sim, 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$ 

Então consigo forçar 'y' para todos, mas não consigo novas falas.

Quando tento yes ''| , não envia um sim.

Eu também gostaria de poder passar um 'n'/'não' também.

E posso ter muitos arquivos, então não estou procurando digitar manualmente yEnterou nEnterpara cada arquivo.

Não me importo com uma solução que não envolva o yescomando.

Responder1

Isto não é tão fácil quanto pode parecer.

Análise

Ao executar cp -ie responder aos prompts de forma interativa, a nova linha que você obtém após digitar yEntervem da disciplina de linha. A disciplina de linha ecoa ye a nova linha.

Você pode observar esse mecanismo executando sole catem um terminal. Ao cataguardar entrada, você pode digitar uma linha longa e até apagar caracteres (com Backspace) ou a linha inteira (com Ctrl+ u); tudo o que você vê é controlado pela disciplina de linha, catapenas fica parado sem qualquer intervenção. Somente quando você bate Enter(ou Ctrl+ m, ou Ctrl+ j), catpega a linha e imprime. A nova linha após o que você digitou é da disciplina de linha, a nova linha após o que catfoi impresso é de cat.

Ou você pode digitar algo e clicar em Ctrl+ dpara enviar catsem nova linha. Então não haverá nova linha após o que você digitou e nenhuma nova linha após o que catfoi impresso.

Da mesma forma, quando solicitado por cp -i, você pode digitar interativamente yCtrl++ dCtrl( dpor que duas vezes?aqui), cpaceitará ye você verá yo eco da disciplina de linha, mas nenhuma nova linha (porque você não digitou nenhuma). cpem si não imprime uma nova linha aqui. Normalmente (ou seja, quando você digita Enter) o que você vê parece correto (ou seja, com novas linhas nos lugares certos) por causa da disciplina de linha. Podemos dizer que cpespera uma disciplina de linha que injete caracteres de nova linha quando apropriado e, assim, faça com que a saída tenha uma boa aparência.

O ponto éuma disciplina de linha entre o teclado e cp -i, ele ecoa o que você digita, incluindo uma nova linha em Enter.

No seu yes | cp -i …, cprecebe entrada quase como se você digitasse yEnterpor meio de uma disciplina de linha, mas desta vez não há nada como uma disciplina de linha que ecoaria o que entra cp. Este é o motivo pelo qual você não observou novas linhas (e nenhum ycaractere).

No caso de yes '' | cp -i …, as novas linhas depois not overwrittenforam impressas por cp. O que falta é uma nova linha antes de cada arquivo not overwritten. Sem yes, se você apenas clicar Enterem resposta ao prompt, verá not overwrittenuma linha separada.


Rumo à solução

Para conseguir o que deseja, você precisa de algo que ecoe a entrada inserida no arquivo cp. À primeira vista, parece que pode ser uma disciplina de linha real (algumas ideias aqui:Como enganar um comando fazendo-o pensar que sua saída está indo para um terminal; observe que não queremos enganar cp, queremos um "efeito colateral" de ter um terminal) ou teeentre yese cp, assim:

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

O procedimento acima não funcionará bem porque yesgera sua saída imediatamente e, tanto quanto possível, é como um usuário que faz um mash, yEnterindependentemente de ser solicitado ou não. Ecoar isso faz com que o resultado pareça muito pior do que o que você postou na pergunta.

Mesmo que você soubesse antecipadamente que precisava de apenas um yEnter, usar echo yem vez de yestambém não funcionaria bem, porque muito provavelmente a entrada seria vista e impressa (pela linha adicionada disciplina ou por tee) antes de cpimprimir seu prompt.


Solução

Uma solução adequada é executar cp -i …com pty adicional, mas apenas fornecer informações quando solicitado. expect(1)pode fazer isso. Este é um expectscript rápido e sujo:

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

Usuários com localização cpdevem ajustar o "overwrite *\\?"padrão.

Esteja ciente de que tenho pouca experiência com o expect, o script pode estar abaixo do ideal ou até mesmo um tanto falho. Trate isso como uma prova de conceito. Salve o script como cpxem um diretório no seu $PATH, torne-o executável ( chmod +x cpx) e use assim:

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

Na prática, pode ser bom definir aliases de shell:

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

e use-os assim:

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

Responder2

Muitas maneiras de ignorar o alias para usar nativo cp:

  • Use o comando integrado:command cp
  • Use o caminho completo do comando:/bin/cp
  • Adicione um \ em qualquer lugar no nome do comando, por exemplo:\cp
  • Cite o comando: "cp"ou'cp'

Responder3

Você pode usar 'sim |' na frente do seu código.

yes | cp -i ?.? smalls

informação relacionada