vim - Como escapar o nome do arquivo contendo aspas simples e duplas?

5

Digamos que eu crie um nome de arquivo com isso:

xb@dnxb:/tmp/test$ touch '"i'"'"'m noob.mp4"'
xb@dnxb:/tmp/test$ ls -1
"i'm noob.mp4"
xb@dnxb:/tmp/test$ 

Em seguida, vim . para entrar na lista de diretórios do Netrw.

" ============================================================================
" Netrw Directory Listing                                        (netrw v156)
"   /tmp/test
"   Sorted by      name
"   Sort sequence: [\/]$,\<core\%(\.\d\+\)\=\>,\.h$,\.c$,\.cpp$,\~\=\*$,*,\.o$,\.obj$,\.info$,\.swp$,\.bak$,\~$
"   Quick Help: <F1>:help  -:go up dir  D:delete  R:rename  s:sort-by  x:special
" ==============================================================================
../
./
"i'm noob.mp4"

Em seguida, pressione Enter para visualizar o arquivo. Tipo:

:!ls -l %

Isso mostrará o erro:

xb@dnxb:/tmp/test$ vim .

ls: cannot access '/tmp/test/i'\''m noob.mp4': No such file or directory

shell returned 2

Press ENTER or type command to continue

Eu também tentei:

[1] :!ls -l '%' :

Press ENTER or type command to continue
/bin/bash: -c: line 0: unexpected EOF while looking for matching '"'
/bin/bash: -c: line 1: syntax error: unexpected end of file

shell returned 1

Press ENTER or type command to continue

[2] :!ls -l "%" :

Press ENTER or type command to continue
/bin/bash: -c: line 0: unexpected EOF while looking for matching '''
/bin/bash: -c: line 1: syntax error: unexpected end of file

shell returned 1

Press ENTER or type command to continue

[3] :!ls -l expand("%") :

/bin/bash: -c: line 0: syntax error near unexpected token '('
/bin/bash: -c: line 0: 'ls -l expand(""i'm noob.mp4"")'

shell returned 1

Press ENTER or type command to continue

[4] !ls -l shellescape("%") :

/bin/bash: -c: line 0: syntax error near unexpected token '('
/bin/bash: -c: line 0: 'ls -l shellescape("/tmp/test/"i'm noob.mp4"")'

shell returned 1

Press ENTER or type command to continue

[5] !ls -l shellescape(expand("%")) :

/bin/bash: -c: line 0: syntax error near unexpected token '('
/bin/bash: -c: line 0: 'ls -l shellescape(expand("/tmp/test/"i'm noob.mp4""))'

shell returned 1

Press ENTER or type command to continue

Meu objetivo final é executar rsync em Ctrl + c , por exemplo:

nnoremap <C-c> :!eval 'ssh-agent -s'; ssh-add; rsync -azvb --no-t % [email protected]:/home/xiaobai/storage/

Minha plataforma é o vim.gtk3 , bash do Kali Linux. vim e gvim do Fedora também têm o mesmo problema.

Qual é a sintaxe correta para escapar do nome do arquivo contendo aspas simples e duplas no vim?

[UPDATE]

exec '!ls -l' shellescape(expand('%')) pode funcionar, mas ainda não consigo descobrir como fazer rsync acima do trabalho. Não tenho idéia de onde devo colocar aspas para este comando mais complexo rsync .

    
por 林果皞 28.10.2016 / 00:36

2 respostas

4

De :help filename-modifiers :

The file name modifiers can be used after "%", "#", "#n", "<cfile>", "<sfile>",
"<afile>" or "<abuf>".  ...

...
    :s?pat?sub?
            Substitute the first occurrence of "pat" with "sub".  This
            works like the |:s| command.  "pat" is a regular expression.
            Any character can be used for '?', but it must not occur in
            "pat" or "sub".
            After this, the previous modifiers can be used again.  For
            example ":p", to make a full path after the substitution.
    :gs?pat?sub?
            Substitute all occurrences of "path" with "sub".  Otherwise
            this works like ":s".

Então, em vez de apenas lidar com aspas duplas ou aspas simples, vamos apenas recuar o escape tudo incomum:

:!ls -l %:gs/[^0-9a-zA-Z_-]/\&/

Funciona perfeitamente com o nome do arquivo de teste que você forneceu.

Para usar um caminho absoluto, que você pode querer para rsync , você pode adicionar :p no final:

:!ls -l %:gs/[^0-9a-zA-Z_-]/\&/:p

Na verdade, também funciona bem se você barra invertida literalmente todos os caracteres, e é mais curto para digitar:

:!ls -l %:gs/./\&/:p

Portanto, no seu comando rsync , em vez de % , use %:gs/./\&/:p .

    
por 28.10.2016 / 04:48
3

Com base na resposta do Wildcard usando os modificadores de nome de arquivo, :S fornece exatamente o que você deseja. De acordo com os documentos ( :h %:S ),

:S      Escape special characters for use with a shell command (see
        |shellescape()|). Must be the last one. Examples:
            :!dir <cfile>:S
            :call system('chmod +w -- ' . expand('%:S'))

Para usar seu exemplo:

$ touch '"I'\''m also a n00b.txt"'
$ ls
"I'm also a n00b.txt"

Em seguida, vim '"I'\''m also a n00b.txt"' e voilà:

:!ls %:S

"I'm also a n00b.txt"

O modificador de nome de arquivo :S é disponível no Vim 7.4 .

    
por 24.06.2018 / 01:14