Eu tenho cerca de 10 php.ini
arquivos no meu sistema, localizados em todo o lugar, e queria procurá-los rapidamente. Eu tentei este comando:
locate php.ini | xargs vi
Mas vi
me avisa Input is not from a terminal
e, em seguida, o console começa a ficar realmente estranho - após o qual eu preciso pressionar :q!
para sair vi
e desconectar da sessão ssh e reconectar para que o console se comporte normalmente novamente.
Eu acho que meio que entendo o que está acontecendo aqui - basicamente, o comando não terminou quando vi
iniciado, portanto o comando talvez não tenha terminado e vi
não pense que o terminal esteja no modo normal.
Não faço ideia de como consertar. Eu pesquisei no Google e também no unix.stackexchange.com com pouca sorte.
command-line
terminal
vi
xargs
cwd
fonte
fonte
reset
reset do seu terminal quando ele estragar (você não precisa desconectar da sessão ssh).Respostas:
Nota: isso terá problemas se os caminhos do arquivo tiverem espaços, mas é funcionalmente equivalente ao seu comando.
Esta próxima versão manipulará corretamente os espaços, mas é um pouco mais complicada (as novas linhas nos nomes de arquivos ainda serão quebradas)
Explicação:
O que está acontecendo é que os programas herdam seus descritores de arquivos do processo que os gerou.
xargs
tem seu STDIN conectado ao STDOUT delocate
, portantovi
, não tem idéia do que o STDIN original realmente está.fonte
xargs
pois isso não poderia ser feito diretamente com o shell (oufind
). No entanto, posso pensar em casos em que seria a melhor solução. Assim, desde que você entenda o quexargs
está fazendo, como ele divide os argumentos, como ele executa o programa, etc, e estão usando-o corretamente, eu diria que ir para ela :-P... | awk '{print $3}' | xargs | sed -e 's/ /+/g' | bc
(somar todos os valores do campo 3). ou comsed -e 's/ /|/g'
para construir uma regexp. e sim, como qualquer ferramenta, você precisa saber como usá-la e quais são suas limitações e advertências.vi $(...)
abordagem também tem um problema com caracteres curinga em outros shellszsh
.xargs
abordagem ao lado do problema de espaço em branco, nomes de arquivos com aspas simples, aspas duplas e barras invertidas também são um problema.Esta questão foi previamente perguntado sobre o usuário Super fórum.
Citando a resposta de @ grawity sobre essa pergunta:
Isso é mencionado nas páginas de manual do xarg. Do OSX / BSD:
Portanto, no OSX, você pode usar o seguinte comando:
Embora não haja opção direta na versão GNU, este comando funcionará. (Certifique-se de incluir a
dummy
sequência, caso contrário ela eliminará o primeiro arquivo.)As soluções acima são cortesia de Jaime McGuigan no SuperUser . Adicionando-os aqui para futuros visitantes pesquisando no site por esse erro.
fonte
xargs sh -c 'emacs "$@" < /dev/tty' emacs
como o que eles alegam ser uma alternativa mais flexível e portátil (embora seja meio engraçado o GNU preferir a portabilidade do que os recursos :).Com GNU
findutils
, e um escudo com suporte para substituição de processo (ksh, zsh, bash), você pode fazer:A idéia é passar a lista de arquivos por meio de um
-a filename
stdin. O uso-0
garante que ele funcione independentemente dos caracteres ou não caracteres que os nomes dos arquivos podem conter.Com
zsh
, você pode fazer:(onde
0
é o sinalizador de expansão de parâmetro a ser dividido em NULs).No entanto, observe que, ao contrário
xargs -r
disso, ainda é executadovi
sem argumento se nenhum arquivo for encontrado.fonte
Editar vários php.ini dentro do mesmo editor?
Experimentar:
vim -o $(locate php.ini)
fonte
Este erro ocorre quando o vim é chamado e está conectado à saída do pipeline anterior, em vez do terminal e recebendo diferentes entradas inesperadas (como NULs). O mesmo acontece quando você executa :,
vim < /dev/null
portanto, oreset
comando neste caso ajuda. Isso é bem explicado pelo grawity no superusuário .No Unix / OSX você pode usar
xargs
com o-o
parâmetro, como:No Linux, tente a seguinte solução alternativa:
Como alternativa, use o GNU em
parallel
vez dexargs
forçar a alocação de tty, no exemplo:Nota:
parallel
no Unix / OSX não funcionará, pois possui parâmetros diferentes e não suporta tty.Muitos outros comandos populares também fornecem alocação pseudo-tty (como
-t
emssh
), portanto, procure ajuda.Como alternativa, use
find
para passar nomes de arquivos para editar; portanto, não precisaxargs
, basta usar-exec
, por exemplo:fonte
@ O
IFS
hack de Patrick é necessário apenas para conchas idiotas comobash
ezsh
.fish
divide a string em novas linhas por padrão.E Deus ajude a todos se um único de nós realmente tiver um arquivo com uma nova linha em seu nome. Depois de 17 anos usando o Linux, eu não o vi nem uma vez. Eu só me incomodaria em dar suporte a nomes de arquivos com novas linhas para scripts que precisam funcionar, não importa o que aconteça, mas scripts como esse provavelmente não estão executando o vim interativamente.
fonte
zsh
divide em SPC, TAB, NL e NUL por padrão. O que ele não faz em comparaçãobash
é observar os resultados, para que os caracteres curinga nos nomes dos arquivos não sejam um problema. Emzsh
, você fariaIFS=$'\0'; vi $(locate -0 php.ini)
ou como mostrei na minha respostavi ${(0)"$(locate -0 php.ini)"}
para um operador de divisão explícito. Observe também o tcshvi "`locate php.ini`"
$ f='not there'<ret>$ ls $f<ret>
mas isso não: lsecho not there
. OK parece que eu preciso atualizar isso um pouco.ls "$(echo test; echo other test)"
. Somente o peixe faz a coisa certa.$IFS
ou via operadores explícitos (f
e0
sinalizadores de expansão de parâmetros). Para nomes de arquivos arbitrários, dividir por palavra ou dividir por linha é igualmente errado , é necessário dividir em NUL ou analisar alguma codificação, o quefish
não pode ser feito. Emzsh
, isso éIFS=$'\0'; ls -ld -- $(printf '%s\0' "$file1" "$file2")
ouls -ld -- ${(0)"$(printf '%s\0' "$file1" "$file2")"}
Uma maneira rápida de fazê-lo, supondo que você pode garantir nenhum dos caminhos de arquivos contêm SPC, TAB, NL,
*
,?
,[
personagens (também\
e{...}
em algumas conchas) é usar back-carrapatos (aka acento grave) para executar um comando antes outro comando em execução.Por exemplo
O comando contido nos back-ticks será executado primeiro. A saída do comando contido é então executada pelo comando indicado antes dos back-ticks.
Por exemplo, na linha acima, o
find / -type f -name 'php.ini'
comando será executado primeiro, enviará a saída e, em seguidavi
, será executado no resultado da divisão + glob aplicada a essa saída.fonte
$(find ...)
vez disso.vi
usando esse método. É bem possível que ele possa quebrar em novas linhas ou espaços, dependendo de comovi
está lendo e executando a saída.