vim - ¿Cómo escapar del nombre de archivo que contiene una combinación de comillas simples y dobles?

vim - ¿Cómo escapar del nombre de archivo que contiene una combinación de comillas simples y dobles?

Digamos que creo un nombre de archivo con esto:

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

Luego, vim .ingrese al listado del directorio 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"

Luego presione Enterpara ver el archivo. Tipo:

:!ls -l %

Mostrará error:

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

También probé:

[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

Mi objetivo final es realizar rsyncpor Ctrl+ c, por ejemplo:

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

Mi plataforma es Kali Linux vim.gtk3, bash. Fedora vimy gvimtambién tienen el mismo problema.

¿Cuál es la sintaxis correcta para escapar del nombre de archivo que contiene comillas simples y dobles en vim?

[ACTUALIZAR]

exec '!ls -l' shellescape(expand('%'))Puede funcionar, pero todavía no puedo entender cómo hacer que rsynclo anterior funcione. No tengo idea de dónde debería poner comillas para este comando más complejo rsync.

Respuesta1

Sobre la base deLa respuesta del comodínEl uso de modificadores de nombre de archivo :Sle brinda exactamente lo que desea. Según los 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 su ejemplo:

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

Entonces vim '"I'\''m also a n00b.txt"', y listo:

:!ls %:S

"I'm also a n00b.txt"

El :Smodificador de nombre de archivo esdisponible en Vim 7.4.

Respuesta2

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".

Entonces, en lugar de simplemente manejar comillas dobles o comillas simples,simplemente hagamos una barra invertida para escapartodoinusual:

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

Funciona perfectamente con el nombre de archivo de prueba que proporcionaste.

Para usar una ruta absoluta, que quizás desees rsync, puedes agregar :pal final:

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

En realidad, también funciona bien si usas una barra invertida y escapas literalmente de cada carácter, y es más corto de escribir:

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

Entonces, bajo tu rsyncmando,en lugar de %, utilizar %:gs/./\\&/:p.

información relacionada