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 rsync
durch 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 vim
und gvim
ich 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 rsync
oben 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 :S
gibt 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 :S
Dateinamenmodifikator 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 :p
am 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 rsync
Befehl%
Verwenden Sie anstelle von %:gs/./\\&/:p
.