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

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

Digamos que eu crie um nome de arquivo com isto:

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 .entre na listagem do diretório 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 Enterpara visualizar o arquivo. Tipo:

:!ls -l %

Ele mostrará 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+ Ctrl, cpor exemplo:

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

Minha plataforma é a do Kali Linux vim.gtk3, bash. Fedora vime gvimtambém tem o mesmo problema.

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

[ATUALIZAR]

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

Responder1

Construindo emResposta do curingausar modificadores de nome de arquivo :Sfornece 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"

Então vim '"I'\''m also a n00b.txt"', e voilà:

:!ls %:S

"I'm also a n00b.txt"

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

Responder2

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 simples,vamos apenas escapar da barra invertidatudoincomum:

:!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ê deseja rsync, você pode adicionar :pno final:

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

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

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

Então, sob seu rsynccomando,em vez de %, use %:gs/./\\&/:p.

informação relacionada