Welcome to Vifm Q&A, where you can ask questions about using Vifm. Registration is optional, anonymous posts are moderated. E-mail and GitHub logins are enabled.
0 votes
in vifm by

I need to use %f inside command wrapped in single quotes, but some elements name contains special character like single quotes and that breaks the command: how do I solve that?

example

su -c 'echo %f' john

1 Answer

0 votes
by
selected by
 
Best answer

Escape the whole command one more time:

su -c "$(printf '%%q ' echo %f)" john
by

there's another way to achieve that?

I tried your proposed solution to a more complex command but failed, quotes and escapes sometimes drives me nuts:

su -c '$(cat /usr/share/applications/$(xdg-mime query default $(xdg-mime query filetype %f)) | grep -oP "(?<=^Exec=).*" | awk "{print \$1}") %f %i' $USER

this code has problem if filenames contains single quote

by

It's probably better to make a script and just invoke it like in the answer.

by
edited by

probably it is, but I'm trying to streamline image, audio and video filextype and I prefer to have all configured in the vifmrc file.

I tried to split that command like this

  \  app=$(cat /usr/share/applications/$(xdg-mime query default $(xdg-mime query filetype %f)) | grep -oP '(?<=^Exec=).*' | awk '{print $1}');
  \  su -c "$app %f %i" $USER

but the filextype section do not seems to digest shell command like the remapping does, right?

by

The caveat is that Vifm tries to check that app=$(cat command exists in $PATH. You can prepend true && to make the check succeed.

by
edited by

I tried this but it still gives me error with filename with ', even if I escaped the whole command, how's that possible?

  \  true &&
  \  app=$(su -c 'xdg-mime query default $(xdg-mime query filetype %f)' $USER);
  \  appcmd=$(cat /usr/share/applications/$app | grep -oP '(?<=^Exec=).*' | awk '{print $1}');
  \  su -c "$appcmd %f %i" $USER

edit it like this still present the same symptoms:

  \  su -c "$(printf '%%q ' $appcmd %f %i)" $USER

the error it gives is

parse error near `)'

and it popups only with filename '

edit: I think it has something to do with the first %f at this point, I'll try that way

edit2: that was it! it finally works now with double quotes! thank for your guidance as always

  \  true &&
  \  app=$(su -c "xdg-mime query default $(xdg-mime query filetype %f)" $USER);
  \  appcmd=$(cat /usr/share/applications/$app | grep -oP '(?<=^Exec=).*' | awk '{print $1}');
  \  su -c "$appcmd %f %i" $USER
by
edited by

Vim has a escape() function that can be used to escape special characters like when matching regex patterns and many other stuff. For example: when matching regex escape(pattern_string, '.*^$[]\(){}+?|') properly escapes the matching characters.

A similar function will be pretty useful for vifm as well.

by

Adding escape() is easy, I think last time it was considered I went for adding fnameescape(). Mind that neither of them could be used to replace printf %q here, because they won't handle separate files in the expansion of %f.

by

maybe introduce a new macro that returns the files list with "\n" at each file name end

by

maybe introduce a new macro that returns the files list with "\n" at each file name end

It won't help with processing them individually and will fall apart on files with newlines in their names.

Something like this might already do escaping by the way (from your regexp example):

%f:gs/([][.*^$\\(){}+?|])/\\\1/
...