vim - Как экранировать имя файла, содержащее смесь одинарных и двойных кавычек?

vim - Как экранировать имя файла, содержащее смесь одинарных и двойных кавычек?

Допустим, я создаю файл с таким именем:

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

Затем vim .заходим в листинг каталога 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"

Затем нажмите Enter, чтобы просмотреть файл. Введите:

:!ls -l %

Будет показана ошибка:

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

Я также попробовал:

[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

Моя конечная цель — выполнить rsync+ Ctrl, cнапример:

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

Моя платформа - Kali Linux vim.gtk3, bash. Fedora vimи gvimу меня та же проблема.

Каков правильный синтаксис для экранирования имени файла, содержащего одинарные и двойные кавычки в vim?

[ОБНОВЛЯТЬ]

exec '!ls -l' shellescape(expand('%'))может работать, но я все еще не могу понять, как заставить rsyncработать вышесказанное. Я понятия не имею, где мне поставить кавычки для этой более сложной команды rsync.

решение1

Опираясь наОтвет Wildcardиспользование модификаторов имени файла, :Sдает вам именно то, что вы хотите. Согласно документации ( :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'))

Используя ваш пример:

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

И вот vim '"I'\''m also a n00b.txt"', вуаля:

:!ls %:S

"I'm also a n00b.txt"

Модификатор :Sимени файла:доступно в Vim 7.4.

решение2

От :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".

Поэтому вместо того, чтобы просто обрабатывать двойные или одинарные кавычки,давайте просто сделаем обратный слеш побегвсенеобычный:

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

Отлично работает с указанным вами именем тестового файла.

Чтобы использовать абсолютный путь, который вам может понадобиться rsync, вы можете добавить :pв конце:

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

На самом деле, это также прекрасно работает, если экранировать обратным слешем буквально каждый символ, и это короче вводить:

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

Итак, по вашему rsyncприказу,вместо %, используйте %:gs/./\\&/:p.

Связанный контент