Gostaria cp
de avisar antes de substituir, então estou usando o -i
.
(Às vezes posso usar um alias para cp
, ou similar, então cp
sempre ocorre com -i
).
Posso querer dizer sobrescrever tudo. Eu sei que esse é o padrão, mas como estou usando, -i
nã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 yes
comando.
Responder1
Isto não é tão fácil quanto pode parecer.
Análise
Ao executar cp -i
e 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 y
e a nova linha.
Você pode observar esse mecanismo executando sole cat
em um terminal. Ao cat
aguardar 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, cat
apenas fica parado sem qualquer intervenção. Somente quando você bate Enter(ou Ctrl+ m, ou Ctrl+ j), cat
pega a linha e imprime. A nova linha após o que você digitou é da disciplina de linha, a nova linha após o que cat
foi impresso é de cat
.
Ou você pode digitar algo e clicar em Ctrl+ dpara enviar cat
sem nova linha. Então não haverá nova linha após o que você digitou e nenhuma nova linha após o que cat
foi impresso.
Da mesma forma, quando solicitado por cp -i
, você pode digitar interativamente yCtrl++ dCtrl( dpor que duas vezes?aqui), cp
aceitará y
e você verá y
o eco da disciplina de linha, mas nenhuma nova linha (porque você não digitou nenhuma). cp
em 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 cp
espera 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 éhá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 …
, cp
recebe 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 y
caractere).
No caso de yes '' | cp -i …
, as novas linhas depois not overwritten
foram 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 overwritten
uma 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 tee
entre yes
e 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 yes
gera 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 y
em vez de yes
também não funcionaria bem, porque muito provavelmente a entrada seria vista e impressa (pela linha adicionada disciplina ou por tee
) antes de cp
imprimir 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 expect
script 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 cp
devem 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 cpx
em 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