Overview
lf (list files) is a terminal file manager written in Go, inspired by ranger but designed with a focus on speed, simplicity, and a small binary size. It provides a three-pane layout (parent, current, preview), vi-like keybindings, and a powerful configuration system that allows users to define custom commands, keybindings, and file previews using shell scripts.
lf is single-binary with no dependencies, making it easy to install and deploy across systems. It supports multi-file selection, bulk operations, shell command execution, bookmarks, marks, and integrates with external tools for file preview, image display, and bulk renaming through a flexible configuration file.
Installation
# macOS
brew install lf
# Arch Linux
sudo pacman -S lf
# Go install
go install github.com/gokcehan/lf@latest
# Conda
conda install -c conda-forge lf
# Download binary
# https://github.com/gokcehan/lf/releases
# Verify
lf --version
Core Navigation
| Key | Action |
|---|
h or Left | Parent directory |
l or Right | Open file/enter directory |
j or Down | Move down |
k or Up | Move up |
gg | Go to top |
G | Go to bottom |
Ctrl+U | Half page up |
Ctrl+D | Half page down |
Ctrl+B | Full page up |
Ctrl+F | Full page down |
~ | Go to home |
/ | Search forward |
? | Search backward |
n | Next search result |
N | Previous search result |
q | Quit |
File Operations
| Key | Action |
|---|
Space | Toggle selection |
v | Invert selection |
u | Unselect all |
y | Yank (copy) |
d | Cut |
p | Paste |
c | Clear yank/cut |
r | Rename |
Delete | Delete (to trash) |
e | Edit with $EDITOR |
i | Open with pager |
w | Open shell |
: | Command prompt |
! | Shell command |
$ | Shell command (wait for key) |
% | Shell pipe command |
& | Shell async command |
Marks and Bookmarks
| Key | Action |
|---|
m + key | Save mark |
' + key | Go to mark |
" + key | Remove mark |
# In lf, press m then a letter to save current dir as bookmark
# Press ' then the letter to jump to it
# Built-in marks:
# ' (apostrophe) - previous directory
Configuration
# Config file location
# ~/.config/lf/lfrc
# Preview script
# ~/.config/lf/preview
# ~/.config/lf/lfrc
# Basic settings
set hidden true
set ignorecase true
set icons true
set previewer ~/.config/lf/preview
set cleaner ~/.config/lf/cleaner
set shell bash
set shellopts '-eu'
set ifs "\n"
set scrolloff 10
set period 1
set findlen 2
set info size:time
set sortby natural
set ratios 1:2:3
set drawbox true
# Custom commands
cmd open ${{
case $(file --mime-type "$f" -bL) in
text/*|application/json) $EDITOR "$fx" ;;
image/*) sxiv "$f" ;;
video/*) mpv "$f" ;;
application/pdf) zathura "$f" ;;
*) xdg-open "$f" ;;
esac
}}
cmd mkdir %{{
printf "Directory name: "
read -r dirname
mkdir -p "$dirname"
}}
cmd mkfile %{{
printf "File name: "
read -r filename
touch "$filename"
}}
cmd trash %{{
files=$(printf "$fx" | tr '\n' ';')
while [ "$files" ]; do
file=${files%%;*}
trash-put "$(basename "$file")"
if [ "$files" = "$file" ]; then
files=''
else
files="${files#*;}"
fi
done
}}
cmd extract ${{
set -f
case "$f" in
*.tar.bz2) tar xjf "$f" ;;
*.tar.gz) tar xzf "$f" ;;
*.tar.xz) tar xJf "$f" ;;
*.bz2) bunzip2 "$f" ;;
*.gz) gunzip "$f" ;;
*.tar) tar xf "$f" ;;
*.zip) unzip "$f" ;;
*.7z) 7z x "$f" ;;
*.rar) unrar x "$f" ;;
esac
}}
cmd zip ${{
set -f
mkdir -p /tmp/lf-zip
cp -r $fx /tmp/lf-zip
cd /tmp/lf-zip
zip -r "$OLDPWD/archive.zip" .
rm -rf /tmp/lf-zip
}}
# Key mappings
map <enter> open
map D trash
map E extract
map Z zip
map a mkfile
map A mkdir
map R reload
map C clear
# Bookmarks
map gh cd ~
map gd cd ~/Documents
map gD cd ~/Downloads
map gp cd ~/Projects
map gc cd ~/.config
map g/ cd /
Preview Script
#!/bin/bash
# ~/.config/lf/preview
# Make executable: chmod +x ~/.config/lf/preview
case "$1" in
*.tar*|*.zip|*.rar|*.7z)
atool --list -- "$1" ;;
*.pdf)
pdftotext "$1" - ;;
*.jpg|*.jpeg|*.png|*.gif|*.bmp|*.webp)
chafa --size="${2}x${3}" "$1" ;;
*.svg)
chafa --size="${2}x${3}" "$1" ;;
*.md)
glow -s dark "$1" ;;
*.json)
jq -C . "$1" ;;
*.csv)
column -t -s, "$1" | head -50 ;;
*)
bat --color=always --style=plain --paging=never \
--terminal-width="$2" "$1" 2>/dev/null ||
cat "$1" ;;
esac
Advanced Usage
Bulk Rename
# Add to lfrc
cmd bulk-rename ${{
old="$(mktemp)"
new="$(mktemp)"
if [ -n "$fs" ]; then
fs="$(basename -a $fs)"
else
fs="$(ls)"
fi
printf '%s\n' "$fs" > "$old"
printf '%s\n' "$fs" > "$new"
$EDITOR "$new"
[ "$(wc -l < "$new")" -ne "$(wc -l < "$old")" ] && exit
paste "$old" "$new" | while IFS="$(printf '\t')" read -r src dst; do
if [ "$src" = "$dst" ] || [ -e "$dst" ]; then
continue
fi
mv -- "$src" "$dst"
done
rm -f "$old" "$new"
lf -remote "send $id reload"
}}
map R bulk-rename
FZF Integration
# Add to lfrc
cmd fzf_jump ${{
res="$(find . -maxdepth 3 | fzf --reverse --header='Jump to:')"
if [ -n "$res" ]; then
if [ -d "$res" ]; then
cmd="cd"
else
cmd="select"
fi
res="$(printf '%s' "$res" | sed 's/\\/\\\\/g;s/"/\\"/g')"
lf -remote "send $id $cmd \"$res\""
fi
}}
map f fzf_jump
Shell cd on Quit
# Add to ~/.bashrc or ~/.zshrc
lfcd() {
tmp="$(mktemp)"
lf -last-dir-path="$tmp" "$@"
if [ -f "$tmp" ]; then
dir="$(cat "$tmp")"
rm -f "$tmp"
[ -d "$dir" ] && [ "$dir" != "$(pwd)" ] && cd "$dir"
fi
}
alias lf='lfcd'
Icons
# Install nerd font first, then set in lfrc:
set icons true
# Create icons file: ~/.config/lf/icons
# Format: extension/type icon
# Example lines:
# di 📁
# fi 📄
# ln ⇒
# ex 🔧
Troubleshooting
| Issue | Solution |
|---|
| Preview not working | Make preview script executable; install bat, chafa |
| Icons not showing | Install a Nerd Font; set set icons true in lfrc |
| Images not displaying | Install chafa or ueberzug; check terminal support |
| cd not working on quit | Use lfcd shell function wrapper |
| Slow on large directories | Disable preview with set nopreview; reduce ratios |
| Key bindings not working | Check for conflicts in lfrc; use map to override |
| Colors not showing | Check $TERM variable; ensure color support |
| Shell commands fail | Check shellopts; verify $SHELL is set correctly |