lf
lf copied to clipboard
Multiple files functionality broken in general?
Well like most I come from ranger, when you try to make something work there it is quite intuitive %f: the highlighted file %d: the path of the current directory %s: the selected files in the current directory %t: all tagged files in the current directory %c: the full paths of the currently copied/cut files %p: the full paths of selected files In lf though, you have some weird $f and its $fs/$fx variants, the distinction between em is not clear. Its not clear when you are dealing with paths and when you are dealing with just filenames. And the best thing is it doesn't really matter, cause it never works with multiple files regardless. Sorry for the rant but yeah, I just wanna pass multiple files to scripts where I can actually do stuff instead of trying to understand Go. In ranger I could just map (map) shell script.sh %s, it really just werks, why doesn't map (map) $script.sh "$fs" or fx ow whatever work with mutliple files in lf?
map M &mpv "$fs" This mapping also doesn't work with multiple files for example. And I wouldn't even need the mapping if open worked on multiple files hmmm (like it does in ranger)
I kinda see the problem is it passes all the file paths on a single text string, so it's not valid filename, let alone multiple of em. But what's the move here? Do I really need to parse or something? What do you guys do?
See the section Shell Commands in the documentation to understand the difference between $f, $fs and $fx. I think you want $fx here. If you come from ranger, you might be interested in using rifle as the opener.
I thought rifle just had to do with what programs opens what mimetype. I have no problem with lf using my systems defaults.
Rifle can actually open multiple files when called like rifle $fx
. Your system's default opener, which is most likely xdg-open, does not support that. You would actually have to program the loop over $fx yourself.
OK, didn't know rifle did that. Thank's for the answer, i'll get it set up.
The open command works as expected now.
I still can't execute scripts though.
I think it passes the filenames such as this:
filename1path<CR>filename2path<CR> etc
While you usually need to pass filename1path filename2path etc (with spaces in between, not carriage returns)
I'm just guessing though. (and yes, i've tried both "$fs" and "$fx")
Finally managed to get it done
cmd myscript ${{ echo -n "$fx" | xargs myscript.sh }}
In my opinion this is needlessly complicated. I know it's just one line, but I had to a bit of digging and finding out how everything works. I don't see the point in the way $fx and $fs pass info, at the very least there should be a flag to get that information separated with spaces in between. It works like that on ranger, and it makes sense because that's how you actually feed information in bash.
lf has a flag for this, it's called ifs
. See https://linuxhint.com/use-ifs-in-bash/ for details. You will need to quote your variables properly to handle file paths with spaces correctly.
Docs say use of set ifs "\n"
is highly recommended. With that option set, I was able to apply actions to multiple files including files that has quotes, spaces, and starts with dash.
This option is not set by default as it can behave unexpectedly for new users.
I don't understand this part though. Some clarity on this would be great.
The discussion on this issue is a testimony for the statement that the ifs
option can behave unexpectedly for [new] users.
To elaborate, setting ifs
is a hack. From Bash Pitfalls: "Nor can you simply change IFS to a newline. Filenames can also contain newlines." You should always double-quote expansions of variables in your scripts (and lfrc) to be sure.
The discussion on this issue is a testimony for the statement that the ifs option can behave unexpectedly for [new] users.
By new user do you mean new to lf?
Nor can you simply change IFS to a newline. Filenames can also contain newlines.
Is that the only reason it's disabled? The devs must be on the paranoid side to consider an extremely rare case. I have no problem with that. I just wish the devs would put this line set ifs "\n"
somewhere near the top of the documentation instead of somewhere near the bottom if it's highly recommended and assumed in the rest of the documentation.
You should always double-quote expansions of variables in your scripts (and lfrc) to be sure.
Have you tried double quoting the variables in lfrc? I tried it and it doesn't work on multiple files even when set ifs "\n"
. Even the wiki doesn't quote it. Other actions that don't involve multiple files have their variables quoted.
It works fine if you set ifs to "\n" as recommended in the documentation (except if your filename has a new line in it).
It works fine if you set ifs to "\n" as recommended in the documentation (except if your filename has a new line in it).
Yah, you're right. I've mistakenly tested $fx on the shell $
not knowing that it doesn't work in the shell. I had to shell-async open it &
for ifs to kick in.
It works with $
too. The only case it doesn't work is if you do $sh
('w' key by default) then use $fx
in the shell. IFS will not be inherited so you have to set it manually. $mpv $fx
works because lf will do something like sh -c "IFS=$'\n'; mpv \$fx"
I think.
Yup. I've tested this specifically in $sh ('w' key) & came to this wrong conclusion. Tq for pointing this out.
I think there's no issue here, but anyway to summarize:
- When multiple files are selected,
$fx
is a string value that contains all the selected filenames separated by the value of thefilesep
option (default"\n"
). - In general, it's probably best to avoid quoting
$fx
in scripts, because using quotes will prevent word splitting and pass the entire string as a single argument. A simple example would bempv $fx
. - When
$fx
isn't quoted, word splitting will be performed on whitespace (defaultIFS
). This includes"\n"
, so the filenames should be split correctly. However if the filenames contain spaces, then splitting will happen there as well, which is why the general advice is to useset ifs "\n"
, to handle filenames that do contain spaces.