Lf: custom open command with files that has spaces in their name

Created on 1 Jun 2020  路  10Comments  路  Source: gokcehan/lf

If I try to use a custom open command, even the one from the docs

cmd open ${{
    case $(file --mime-type $f -b) in
        text/*) $EDITOR $fx;;
        *) for f in $fx; do open $f > /dev/null 2> /dev/null & done;;
    esac
}}

Then open doesn't work with filenames with spaces in them, I tried this but it didn't work too.

cmd open ${{
    case $(file --mime-type $f -b) in
        text/*) $EDITOR "$fx";;
        *) for f in $fx; do open "$f" > /dev/null 2> /dev/null & done;;
    esac
}}

The files I tested this one looked like this:

  • FOO - confirmation.txt -> when I try to open this one, lf just hangs
  • Foo Bar Baz.txt -> when I try to open this one lf flashes but nothing happens

Kapture 2020-06-01 at 18 16 04

It doesn't matter what extension, if the files have spaces then the same behaviour will happen if I don't use a custom open command everything works as expected.

I'm using macOS 10.15.5 & zsh 5.8.

question

All 10 comments

I can't reproduce that.my open command is from lfrc.example
it seems your file is empty, check this issue #339

@shabahengam It doesn鈥檛 matter if the file is empty or not. I tested this with empty files and with some PDFs I have (_the main issue was with a PDF actually_). Same issue.

I tested many files(mp4,mp3,txt,pdf,jpg...) and still can't reproduce the issue.
whats the output of this command-> xdg-mime query default application/pdf
for me its xpdf because I set xpdf for pdf files.

I tested many files(mp4,mp3,txt,pdf,jpg...) and still can't reproduce the issue.
whats the output of this command-> xdg-mime query default application/pdf
for me its xpdf because I set xpdf for pdf files.

I'm using macOS not Linux, will update the main description

a) if you run file --mime-type -b on an empty file, it will most likely return inode/x-empty, even if the file name ends with ".txt" (where you might expect text/plain). hence, the empty file will not get opened by the $EDITOR you defined for text/*, but handled by the default open.

b) if you are using \n as filesep (which is lf's default), you also have to (temporarily) set the shell's field separator (IFS) to the newline character when expanding and reading fx:

IFS0="$IFS"; IFS="$(echo -en "nb")";
for f in ${fx[@]}; do open "$f"; done;
IFS="$IFS0";

otherwise, the shell will (by default) also interpret spaces and tabs as separators and won't read spaced filenames correctly.

c) in your custom command, you only check the mime type of the current file $f, but afterwards you potentially open all selected files $fx with the same viewer/editor. this might cause problems if not all selected files can be opened with the same editor. i would either use only the current file, or iterate over all selected files and separately check their mime types.

a) if you run file --mime-type -b on an empty file, it will most likely return inode/x-empty, even if the file name ends with ".txt" (where you might expect text/plain). hence, the empty file will not get opened by the $EDITOR you defined for text/*, but handled by the default open.

I think the example I showed is causing some confusion, here is a real example to show the problem, these files are not empty.

To demonstrate I downloaded this PDF & renamed it twice to match the patterns I mentioned above

Kapture 2020-06-03 at 10 39 10

running file --brief --mime-type <file> on both files will return application/pdf as expected

and this is the custom open command I used.

cmd open ${{
  case $(file --brief --mime-type $f) in
    text/*) $EDITOR $fx;;
    *) for f in $fx; do $OPENER $f > /dev/null 2> /dev/null & done;; 
  esac
}}

If I run open vim\ -\ manual.pdf it works fine, my guess is that spaces are not escaped properly. So when the files are passed to $OPENER they are passed as multiple arguments instead. And quoting "$f" or "$fx" doesn't help. Hence the confusion & the issue.

b) if you are using \n as filesep (which is lf's default), you also have to (temporarily) set the shell's field separator (IFS) to the newline character when expanding and reading fx:

IFS0="$IFS"; IFS="$(echo -en "nb")";
for f in ${fx[@]}; do open "$f"; done;
IFS="$IFS0";

otherwise, the shell will (by default) also interpret spaces and tabs as separators and won't read spaced filenames correctly.

If I add IFS="`printf '\n\t'`"; before the commands, it solves the Foo Bar Baz.pdf pattern, but not the Foo - Bar.pdf one.

c) in your custom command, you only check the mime type of the current file $f, but afterwards you potentially open all selected files $fx with the same viewer/editor. this might cause problems if not all selected files can be opened with the same editor. i would either use only the current file, or iterate over all selected files and separately check their mime types.

That's the cmd from the docs https://godoc.org/github.com/gokcehan/lf#hdr-Opening_Files, I copied it to try it, but it's a good point.

a) i assume that the line you posted (IFS="printf '\n\t'";), is just misformatted and actually reads IFS="$(printf '\n\t')";.

b) i'm not sure if this is also true for tabs, but most shells remove trailing newline characters before substituting with the standard output from the subshell. try setting the field separator as i suggested, namely with a backspace at the end (IFS="$(echo -en "\n\b")";), or alternatively use the short $ version IFS=$'\n' (not sure if this is part of POSIX standard).

c) on my system (ubuntu 16.04 with xdg-open as default opener) it works correctly for the exact same filenames that you provided.

a) i assume that the line you posted (IFS="printf '\n\t'";), is just misformatted and actually reads IFS="$(printf '\n\t')";.

Yes, I was using backticks instead of $()

b) i'm not sure if this is also true for tabs, but most shells remove trailing newline characters before substituting with the standard output from the subshell. try setting the field separator as i suggested, namely with a backspace at the end (IFS="$(echo -en "\n\b")";), or alternatively use the short $ version IFS=$'\n' (not sure if this is part of POSIX standard).

I modified the cmd to get errors instead of redirecting them & tried your suggestions:

  • IFS="$(echo -en "\n\b")"; didn't work:

    1. for Foo - Bar.pdf in still hangs
    2. for Foo Bar Baz.pdf it showed this error, which shows that file name was split & not passed as a whole.
    The file /privat does not exist.
    The file /tmp/lf does not exist.
    The file /private/tmp/lf-test/t does not exist.
    The file /private/tmp/lf-test/st/vim does not exist.
    The file /private/tmp/lf-test/ma does not exist.
    The file /private/tmp/lf-test/ual does not exist.
    The file /private/tmp/lf-test/fil does not exist.
    The file /private/tmp/lf-test/.pdf does not exist.
    
  • IFS=$'\n' (same as IFS="$(printf '\n\t')") worked for case 2 but case 1 still the same behavior.

c) on my system (ubuntu 16.04 with xdg-open as default opener) it works correctly for the exact same filenames that you provided.

Could it be OS or shell related issue? I'm also using zsh 5.8

i'm using bash 4.3.48. since it should also be pre-installed on your macOS, you could temporarily try using bash as lf's default shell (export SHELL="bash" and set shell bash) to check if the issue is zsh-related.

otherwise, i have no further suggestions and you should wait for comments of more experienced users, and or users that use macOS+zsh and can reproduce your problem.

This solved the problem set ifs "\n"

Was this page helpful?
0 / 5 - 0 ratings

Related issues

doronbehar picture doronbehar  路  3Comments

marcosrdac picture marcosrdac  路  3Comments

muellerto picture muellerto  路  8Comments

wheatdog picture wheatdog  路  6Comments

itmitica picture itmitica  路  6Comments