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を実行することです。例:Ctrlc

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

私のプラットフォームは Kali Linux のvim.gtk3bash です。Fedora のvimでもgvim同じ問題が発生します。

vim で一重引用符と二重引用符を含むファイル名をエスケープするための正しい構文は何ですか?

[アップデート]

exec '!ls -l' shellescape(expand('%'))動作しますが、それでもrsync上記を動作させる方法がわかりません。このより複雑なコマンドでは引用符をどこに配置すればよいのかわかりませんrsync

答え1

構築するワイルドカードの答えファイル名修飾子を使用すると、: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

関連情報