vim – Wie entkommt man einem Dateinamen, der eine Mischung aus einfachen und doppelten Anführungszeichen enthält?

vim – Wie entkommt man einem Dateinamen, der eine Mischung aus einfachen und doppelten Anführungszeichen enthält?

Nehmen wir an, ich erstelle einen Dateinamen wie folgt:

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

Gehen Sie dann vim .in die Netrw-Verzeichnisliste.

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

Drücken Sie dann Enter, um die Datei anzuzeigen. Geben Sie ein:

:!ls -l %

Es wird der folgende Fehler angezeigt:

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

Ich habe auch versucht:

[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

Mein ultimatives Ziel ist die Leistung rsyncdurch Ctrl+ c, zB:

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

Meine Plattform ist Kali Linux vim.gtk3, Bash. Fedora vimund gvimich habe auch das gleiche Problem.

Was ist die richtige Syntax, um in vim Dateinamen mit einfachen und doppelten Anführungszeichen zu maskieren?

[AKTUALISIEREN]

exec '!ls -l' shellescape(expand('%'))kann funktionieren, aber ich kann immer noch nicht herausfinden, wie ich das rsyncoben genannte zum Laufen bringe. Ich habe keine Ahnung, wo ich bei diesem komplexeren Befehl Anführungszeichen setzen soll rsync.

Antwort1

Aufbauend aufWildcards Antwortdie Verwendung von Dateinamenmodifizierern :Sgibt Ihnen genau das, was Sie wollen. Laut der Dokumentation ( :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'))

Um Ihr Beispiel zu verwenden:

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

Dann vim '"I'\''m also a n00b.txt"', und voilà:

:!ls %:S

"I'm also a n00b.txt"

Der :SDateinamenmodifikator istverfügbar in Vim 7.4.

Antwort2

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

Anstatt also nur doppelte oder einfache Anführungszeichen zu verarbeiten,lass uns einfach einen Backslash verwendenallesungewöhnlich:

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

Funktioniert perfekt mit dem von Ihnen angegebenen Testdateinamen.

Um einen absoluten Pfad zu verwenden, was für Sie möglicherweise wünschenswert ist rsync, können Sie :pam Ende hinzufügen:

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

Tatsächlich funktioniert es auch einwandfrei, wenn Sie buchstäblich jedes Zeichen mit einem Backslash maskieren, und es ist kürzer einzutippen:

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

Unter Ihrem rsyncBefehl%Verwenden Sie anstelle von %:gs/./\\&/:p.

verwandte Informationen