├── screenshot.png ├── README.md └── filemanager /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sc0ttj/fzf-filemanager/HEAD/screenshot.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fzf filemanager 2 | 3 | A file manager for the terminal, using `fzf`. 4 | 5 | ## Screenshot 6 | 7 | ![screenshot of fzf filemanager in mlterm](screenshot.png "fzf filemanager in mlterm") 8 | 9 | ## Features 10 | 11 | - fast navigation 12 | - sensible key bindings 13 | - easy directory & file searching 14 | - file previews of various types 15 | - open selected file(s) in various programs, based on MIME type or extension 16 | - integrated command prompt 17 | 18 | Has 2 modes: 19 | 20 | - filemanager: browse and select files and folders 21 | - shellprompt: run commands on the current selection 22 | 23 | This is a hack, not than a proper thing, don't expect too much. 24 | 25 | ## Requirements 26 | 27 | - `fzf` - used for filtering and choosing files & dirs 28 | - `exa` - used for listing dirs (supports `.gitignore`, icons, ..) 29 | - `bat` - used for colourful file previews 30 | - `fd` - used for Alt-C (finding lots of dirs, many levels deep) 31 | 32 | The above dependences (except `fzf`) could be replaced with regular GNU tools like `ls`, `cat`, `find`. 33 | 34 | ## Install 35 | 36 | Copy `filemanager` to a folder in your `$PATH`. 37 | 38 | ## Usage 39 | 40 | ``` 41 | filemanager [-fs] [path/to/dir] 42 | 43 | ``` 44 | 45 | You can load _fzf filemanager_ fullscreen (`-fs`) and pass the directory to start in. 46 | 47 | ## "file manager" mode 48 | 49 | You can navigate around your files and folders, TAB to multi-select, 50 | or ENTER to open current selection, ESC to clear your selection. 51 | 52 | If you open one file, it's mime-type will be used to decide what to do. 53 | 54 | If you open many files, and they're of the same type, they will all be 55 | opened together in the same program (your preferred, editor, player, etc). 56 | 57 | If you chose files of different types, they'll be opened one after the other. 58 | 59 | Alternatively, you can TAB select multiple files and press `!` to open the 60 | "shellprompt" mode, where you can run any commands you like against the selection. 61 | 62 | ## "shell prompt" mode 63 | 64 | Here you can run commands on the "current selection" (the files/dirs you 65 | chose using enter or tab, in the file manager). 66 | 67 | You will see a long list of commands, type to filter them and choose the 68 | command you want to run. 69 | 70 | Hit enter to run the chosen command on _each item_ in the "current selection". 71 | 72 | ## Key bindings 73 | 74 | ### Key bindings: all modes 75 | 76 | - **!** - enter/exit shell prompt mode 77 | - **ctrl-q** - quit 78 | 79 | ### Key Bindings: "filemanager" mode 80 | 81 | 1. Navigation: 82 | 83 | - **up/down** - move up and down the file/dir list 84 | - **left** - cd to `..` 85 | - **right** - cd into the current dir, or open the currently selected file(s) 86 | - **shift+up/down** or **page-up/page-down** - move up and down, half a page at a time 87 | - **shift+left/right** or **] and [** - scroll the preview panel up and down 88 | 89 | 2. Choosing items: 90 | 91 | - **enter** or **/** - choose item 92 | - **tab** - toggle item (multi select) and move down 93 | - **shift-tab** - toggle item (multi-select) and move up 94 | - **escape** - clear selection 95 | 96 | 3. File manager controls 97 | 98 | - **shift+/** - (the `?` key) a help menu showing the controls 99 | - **ctrl-l** - toggle "long" (detailed) list view 100 | - **ctrl-h** - toggle show/hide hidden files 101 | - **ctrl-p** - toggle show/hide the preview panel 102 | - **alt-c** - list & filter all dirs from `.`, hit enter to `cd` into one 103 | 104 | 4. Searching 105 | 106 | Just type stuff while in any dir to start filtering the list. 107 | 108 | ### Key Bindings: "shell prompt" mode 109 | 110 | - **up/down** - move up and down the command list 111 | - **shift+up/down** - move up and down your command history 112 | - **tab** - complete the selected command, in one go 113 | - **enter** - choose and run the chosen command on the selected files/dirs 114 | - **ctrl-q** - exit back to main prompt menu, or exit program 115 | 116 | ## Contributing 117 | 118 | **Pull Requests** welcome. 119 | 120 | Just read the Issues page, pick one, fix it, issue a PR. 121 | 122 | Also see the lines marked `@TODO`, at the top of the script itself. 123 | 124 | -------------------------------------------------------------------------------- /filemanager: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # a simple terminal based file browser, using fzf and exa. 4 | # 5 | # Browse through folders and open files in $EDITOR.. This file browser can be 6 | # loaded using the `Alt-i` key binding (see ~/.bash/keybindings.bash) 7 | 8 | 9 | # @TODO fix image previews: see https://github.com/Ckath/fuf 10 | # 11 | # @TODO fix broken navigation when spaces exist in dir names and file names 12 | # 13 | # @TODO add help panels to each mode, showing key bindings 14 | # 15 | # @TODO add only "relevant" cmds to history (in func create_shellprompt_history) 16 | # - grep selection list, check extensions and mime types 17 | # - work out "group" from mime type (audio, video, text, torrents, archives, etc) 18 | # - get commands matching the given group from a list of cool one liners 19 | # 20 | # @TODO clean up end of script.. files are opened by "group", "extension" or "mime-type" 21 | # 22 | # @TODO fix & finish previews of non-text files, using something other than bat 23 | # 24 | # @TODO fix "shellprompt" mode: support commands like these: `mv {}` 25 | 26 | test -d "$1" && builtin cd "$1" 27 | 28 | mkdir -p /tmp/fzf 29 | chmod 777 /tmp/fzf 30 | 31 | function print_filemanager_header { 32 | header_top=" ${1:-$PWD}" 33 | echo "$header_top" 34 | [ "$PWD" = "/" ] && echo "/" || echo " .." 35 | } 36 | 37 | # get the "main" list of dirs, using exa, 38 | # passed to fzf in "filemanager" mode 39 | function list_dirs { 40 | exa \ 41 | $showhidden \ 42 | $longfilemanager \ 43 | --icons \ 44 | --classify \ 45 | --git \ 46 | --git-ignore \ 47 | --ignore-glob '.git|.cache|buffers' \ 48 | --group-directories-first \ 49 | --colour=always \ 50 | --level 1 "${1:-$PWD}" | sed "s/\*$//g" 51 | } 52 | 53 | # Alt-C triggers a new fzf window, uses this list, gets 54 | # lots of dirs, 8 levels deep, using fd, or 2 levels 55 | # deep using exa 56 | function list_dirs_for_fzcd { 57 | local dir_list="" 58 | if [ "$(which fd)" != "" ];then 59 | dir_list=$(fd \ 60 | --max-results 1000 --type d --absolute-path --max-depth 8 \ 61 | --hidden --exclude "__pycache__*" --exclude "*.default*" \ 62 | --exclude ".git/*" --exclude ".mednafen/b*" --exclude "*OpenWith*") 63 | else 64 | dir_list=$(exa \ 65 | -a --git-ignore \ 66 | --ignore-glob '*mednafen*|*.cache*|*lock*|*.git*|*OpenWith*|*__pycache__*' \ 67 | --oneline -D -R --level=2 \ 68 | | grep -v "^$" \ 69 | | sed -e 's/:$//g' -e 's/$/\//g' -e 's/^\.\///g' \ 70 | | sort -u \ 71 | | while read line; do 72 | test -d "$line" && echo "$line" 73 | done) 74 | fi 75 | [ "$dir_list" != "" ] && echo "$dir_list" 76 | } 77 | export -f list_dirs_for_fzcd 78 | 79 | # get all files in the current dir, one per line 80 | function ls_pwd_contents_one_per_line { 81 | ls -1 --group-directories-first --classify "${1:-$PWD}" 82 | } 83 | 84 | # give fzf a list of dirs (filemanager) or commands (shellprompt) 85 | function get_list_for_fzf { 86 | if [ ! -f /tmp/fzf/shellprompt ];then 87 | print_filemanager_header 88 | echo "$(list_dirs)" 89 | else 90 | # print list of commands to search, instead of a list of dirs 91 | echo ' 92 | xmessage # popup message 93 | chmod -x -- # make non exec 94 | chmod +x -- # make exec 95 | chmod -x # make non exec 96 | chmod -x # make non exec 97 | $EDITOR # open in text editor 98 | extract # extract archive 99 | file -m -b # get file mime type 100 | htop # monitor system processes and programs 101 | mpv -- # play file 102 | mpv -fs -- # play file fullscreen 103 | mplayer -- # play file 104 | mplayer -fs -- # play file fullscreen 105 | pkg install # install the given package file(s) 106 | pkg uninstall # uninstall the given package file(s) 107 | pkg c # list contents of package(s) 108 | pkg ps # get detailed package status 109 | pkg PS # get detailed package status 110 | pkg dir2pet # create a PET package from a directory 111 | pkg dir2sfs # create an SFS package from a directory 112 | rmdir # remove directory 113 | rm # remove file 114 | stat -f # get some details of file(s) 115 | tail -f # show end of file(s) 116 | w3m -dump # open in console browser as plain text 117 | ' 118 | # append commands from $HOME/bin to the list 119 | [ -d $HOME/bin ] && ls -1 $HOME/bin 120 | ls /usr/local/bin/ /usr/bin /usr/sbin/ /bin /sbin | sort -u 121 | fi 122 | } 123 | 124 | function strip_icons_from_fzf_output { 125 | rev \ 126 | | cut -f1 -d' ' \ 127 | | rev \ 128 | | sed \ 129 | -e 's/\[[0-9];[0-9][0-9]m//g' \ 130 | -e 's/\[[0-9];[0-9];[0-9][0-9]m//g' \ 131 | -e 's/\[0m//g' \ 132 | -e 's///g' 133 | } 134 | 135 | # remember user input ("query") or not: 136 | # - dont remember it if query matches nothing in $PWD (causes 137 | # infinite loop) 138 | # - enable the relevant --query option if a line in query 139 | # did match something in $PWD 140 | function set_remembered_query_or_not { 141 | ls -1 "${PWD}" | grep -m1 -q "${query_text}" && usequery=true 142 | [ "$usequery" = true ] \ 143 | && query_text="$([ -f /tmp/fzf/querytext ] && cat /tmp/fzf/querytext)" \ 144 | && [ "$query_text" != "" ] && query="--query=${query_text// /}" 145 | } 146 | 147 | # if filmanager long view, search column 8 onwards, 148 | # if filemanager normal view, search column 2 onwards 149 | # if shellprompt, search column one onwards 150 | function get_column_to_search { 151 | local nth=2 152 | if [ ! -f /tmp/fzf/shellprompt ] && [ -f /tmp/fzf/longfilemanager ];then 153 | nth='8..-1' # long detailed list view 154 | else 155 | nth='2..-1' # short list view 156 | fi 157 | [ -f /tmp/fzf/shellprompt ] && nth='..' 158 | echo -n $nth 159 | } 160 | 161 | # ------- end of functions --------- 162 | 163 | 164 | # disable the "shellprompt" mode, always load in 165 | # "file manager" mode first 166 | rm /tmp/fzf/shellprompt 2>/dev/null 167 | 168 | # <--~~ start the main program loop ~~--> 169 | # pass contents of $PWD to fzf choose a dir to cd and reload, choose 170 | # a file to open it, hit ! to toggle to shellprompt mode. 171 | while :; do 172 | 173 | # each times filemanager reloads, we want to reset some stuff 174 | showhidden='' 175 | header_text="? for help" 176 | # header_text="↑,↓,←,→,⏎,],[ ! for shell tab/shft-tab ctrl-h/p/l/q" 177 | #header_text="controls: move ↑,↓,←,→,⏎ move preview ],[ shell ! help ? " 178 | header_text="${header_text} " 179 | 180 | prompt_text="Search: " 181 | query="" 182 | query_text="$(cat /tmp/fzf/querytext 2>/dev/null)" 183 | usequery=false 184 | fullscreen='' 185 | hidepreview='' 186 | longfilemanager='' 187 | disablesearch='' 188 | shellprompt_options='' 189 | history_file='' 190 | # Show hidden files or not 191 | [ -f /tmp/fzf/showhidden ] && showhidden='-a' 192 | [ -f /tmp/fzf/longfilemanager ] && longfilemanager='--long' 193 | # Enable/disable previe wpanel 194 | [ ! -f /tmp/fzf/showpreview ] && hidepreview=":hidden" 195 | # Enable/disable fullscreen 196 | echo "$@" | grep -qE '\-fs |\-fs$' && fullscreen='--no-height' 197 | set_remembered_query_or_not 198 | # draw preview panel 199 | preview_panel="VAL={2}; [ -f {8} -o -d {8} ] && VAL={8}; test -f \$VAL && \ 200 | { 201 | file -biz \$PWD/\$VAL | grep ^text &>/dev/null && { 202 | echo \$PWD/\$VAL | xargs bat --color=always --decorations=never; 203 | } 204 | file -biz \$PWD/\$VAL | grep ^image &>/dev/null && { 205 | w3mimg.sh \$PWD/\$VAL 206 | } 207 | file -biz \$PWD/\$VAL | grep '/pdf' &>/dev/null && { 208 | zathura \$PWD/\$VAL 209 | } 210 | file -biz \$PWD/\$VAL | grep -E '^video|audio' &>/dev/null && { 211 | mpv \$PWD/\$VAL 212 | } 213 | file -biz \$PWD/\$VAL | grep 'x-tar' &>/dev/null && { 214 | tar -tvf \$PWD/\$VAL 215 | } 216 | } \ 217 | || \ 218 | { \ 219 | [ \$VAL != \$PWD ] && exa \ 220 | $showhidden \ 221 | --oneline \ 222 | --git-ignore \ 223 | --git \ 224 | --colour=always \ 225 | --icons \ 226 | --group-directories-first \ 227 | --classify \ 228 | --level 1 \ 229 | \$VAL 2>/dev/null 230 | } 231 | " 232 | 233 | # draw shellprompt header text 234 | shellprompt_header_text=" 235 | - Type stuff to filter the commands 236 | - Tab to auto complete a command 237 | - Up/Down to cycle through the commands 238 | - Shift-Up/ to cycle through the command history 239 | 240 | Current directory: $PWD 241 | 242 | Current selection (\"\$@\"): 243 | 244 | $(cat /tmp/fzf/selection 2>/dev/null) 245 | 246 | Enter a command to run on the current selection: " 247 | 248 | # set the key binding for enter key, used like so 249 | # --bind="enter:$var" 250 | enter_binding=accept 251 | 252 | # set key binding for / key 253 | fslash_binding='--bind /:accept' 254 | 255 | # Enable/disable shell prompt mode: 256 | # - user can enter commands on the selected items, "$@" 257 | # - disables the "as you type" result filtering 258 | # - changes prompt "icon" 259 | # - changes header text 260 | if [ -f /tmp/fzf/shellprompt ];then 261 | header_text="$shellprompt_header_text" 262 | # text shown before (left of) the user input 263 | prompt_text="$ " 264 | hidepreview=":hidden" 265 | longfilemanager="" 266 | usequery=false 267 | # uncomment below to prevent input being a search thing 268 | #disablesearch="--phony" 269 | 270 | enter_binding='replace-query+execute(echo {n} > /tmp/fzf/selectedline; \ 271 | echo {q} > /tmp/fzf/querytext;)+abort+execute:\ 272 | cat /tmp/fzf/selection | \ 273 | while read selected; \ 274 | do \ 275 | $(echo {} | sed -e "s/#.*//g" -e "s/ //g") "$selected" | IFS=$'\n' fzf --phony --info=hidden --prompt="" --black; \ 276 | done' 277 | 278 | # dont allow / to trigger accept(), as in file browser view, 279 | # let it be typed out normally 280 | fslash_binding='' 281 | 282 | # NOTE! 283 | # I cannot make fzf cannot parse any spaces at all in 284 | # $shellprompt_options! Solution: put the vars _inside_ 285 | # the execute() calls 286 | 287 | # set the fzf settings we want for the "shellprompt" mode 288 | shellprompt_options=" 289 | --bind left:backward-char 290 | --bind right:forward-char 291 | --bind shift-up:previous-history 292 | --bind shift-down:next-history 293 | --bind up:up 294 | --bind shift-tab:up 295 | --bind down:down 296 | --bind tab:replace-query 297 | --bind ctrl-p:ignore 298 | --layout=reverse-list 299 | --query=" 300 | 301 | # tell fzf to use that history 302 | history_file="--history=/tmp/fzf/cmd_hist" 303 | fi 304 | 305 | # selected is the name of the file(s) or dir(s) we will select using fzf 306 | # 307 | # - if its a dir, cd into it, run this loop again 308 | # - if its a file, process it by file type and mime type 309 | # 310 | selected=$(get_list_for_fzf \ 311 | | IFS=$'\n' fzf \ 312 | $query \ 313 | $disablesearch \ 314 | $fullscreen \ 315 | $history_file \ 316 | --filepath-word \ 317 | --select-1 \ 318 | --multi \ 319 | --tabstop=4 \ 320 | --ansi \ 321 | --no-border \ 322 | --nth=$(get_column_to_search) \ 323 | --no-bold \ 324 | --no-hscroll \ 325 | --border \ 326 | --margin=0% \ 327 | --info=hidden \ 328 | --header="$header_text" \ 329 | --header-lines=0 \ 330 | --prompt="$prompt_text" \ 331 | --preview-window right:82:noborder"$hidepreview" \ 332 | --preview "$preview_panel" \ 333 | --bind '~:execute(xmessage current_line="\"{}\" toggled=\"$(cat {+f})\" \"PWD=$PWD\"" ### <-- replace)' \ 334 | --bind '?:execute(xmessage "HELP MENU")' \ 335 | --bind 'alt-/:execute(xmessage "PWD=$PWD")' \ 336 | --bind 'ctrl-/:execute(xmessage "PWD=$PWD")' \ 337 | --bind 'ctrl-a:select-all' \ 338 | --bind 'change:top' \ 339 | --bind 'pgup:half-page-up' \ 340 | --bind 'pgdn:half-page-down' \ 341 | --bind 'shift-up:half-page-up' \ 342 | --bind 'shift-down:half-page-down' \ 343 | --bind 'shift-left:preview-page-up' \ 344 | --bind 'shift-right:preview-page-down' \ 345 | --bind '[:preview-page-up' \ 346 | --bind ']:preview-page-down' \ 347 | --bind 'left:execute-silent(rm /tmp/fzf/querytext;)+clear-query+clear-selection+unix-line-discard+top+down+reload(builtin cd ..; echo "..")+top+down+accept' \ 348 | --bind 'right:execute-silent(rm /tmp/fzf/querytext;)+accept' \ 349 | --bind '!:execute(\ 350 | cat "{+f}" | rev | cut -f1 -d" " | rev > /tmp/fzf/selection)+execute( 351 | [ ! -f /tmp/fzf/shellprompt ] \ 352 | && echo {q} > /tmp/fzf/shellprompt \ 353 | || rm /tmp/fzf/shellprompt; 354 | [ -f /tmp/fzf/shellprompt ] \ 355 | && echo {q} > /tmp/fzf/querytext)+abort' \ 356 | --bind 'alt-c:abort+execute(echo QUIT; list_dirs_for_fzcd | IFS=$"\n" fzf --select-1 | exec xargs filemanager)' \ 357 | --bind 'ctrl-o:accept' \ 358 | --bind 'ctrl-p:toggle-preview+execute(\ 359 | [ ! -f /tmp/fzf/showpreview ] && touch /tmp/fzf/showpreview || rm /tmp/fzf/showpreview; \ 360 | )' \ 361 | --bind 'ctrl-l:clear-selection+clear-query+execute-silent(\ 362 | [ ! -f /tmp/fzf/longfilemanager ] \ 363 | && touch /tmp/fzf/longfilemanager \ 364 | || rm /tmp/fzf/longfilemanager; \ 365 | )+top+accept' \ 366 | --bind 'ctrl-h:clear-selection+execute-silent(\ 367 | [ ! -f /tmp/fzf/showhidden ] \ 368 | && touch /tmp/fzf/showhidden \ 369 | || rm /tmp/fzf/showhidden \ 370 | )+top+accept' \ 371 | --bind 'ctrl-q:clear-selection+execute(echo QUIT)+abort' \ 372 | --bind 'esc:clear-selection' \ 373 | $shellprompt_options \ 374 | --bind "enter:$enter_binding" \ 375 | $fslash_binding \ 376 | | strip_icons_from_fzf_output) 377 | 378 | 379 | # phew .. now have a newline separated list of more or more things 380 | # in $selection, so lets do something with it... 381 | 382 | if [ -d "$selected" ];then 383 | builtin cd "$selected" 384 | elif [ "$selected" = "QUIT" ];then 385 | break 386 | else 387 | selected=$(echo "$selected" | tr '\n' ' ') 388 | # we _finally_ have our selection... 389 | # now... lets go through the files (or dirs) we have in 390 | # $selected, and choose what to do with them, based on type 391 | 392 | # if all selected files are of the same type, open them all at once 393 | file_cmd='' 394 | files='' 395 | # for each $f, set the cmd to run based on its mime type, 396 | # and add it to $files 397 | for f in $selected 398 | do 399 | case "$(file --mime-type -b "$f")" in 400 | text*|app*text*|app*json|app*csv|app*perl|app*php|app*pyt*|app*ruby|app*script|app*xml) 401 | [ -f "$f" ] \ 402 | && file_cmd="${EDITOR:-vi}" \ 403 | && files="${files} $f" 404 | ;; 405 | image*) 406 | [ -f "$f" ] \ 407 | && file_cmd="feh -Z -x -F -B black" \ 408 | && files="${files} $f" 409 | ;; 410 | esac 411 | done 412 | # if we found a match, run the cmd against the files, 413 | # then continue loop (back to get dirs + fzf) 414 | [ "$file_cmd" != "" ] \ 415 | && [ "$files" != "" ] \ 416 | && $file_cmd $files && continue 417 | 418 | # if still no match, process archive files 419 | for f in $selected 420 | do 421 | # get the full path to $f as $file and its dir as $folder 422 | function get_filepath { 423 | file="$f" 424 | folder=$(dirname "$f" | xargs realpath) 425 | [ "$folder" = "$PWD" ] \ 426 | && folder="$folder/${file%.*}" \ 427 | && folder="${folder//.tar/}" 428 | file=$(realpath "$f") 429 | } 430 | # mv foo/foo/* to foo/*, if needed 431 | function archive_cleanup { 432 | spare_dir=$(echo "$folder/$(basename "$folder")" | sed 's|//|/|g') 433 | if [ -d "$spare_dir" ] \ 434 | && [ "$spare_dir" != "" ] \ 435 | && [ "$spare_dir" != '/' ] 436 | then 437 | mv "$spare_dir/"* "$folder/" 438 | rmdir "$spare_dir" 439 | fi 440 | } 441 | 442 | # try to unpack $f, and continue back to fzf if successful 443 | ( 444 | # get full paths of archive, empty for now, but we'll use 445 | # get_filepath to set values from $f 446 | file='' 447 | folder='' 448 | case "$f" in 449 | *.tar.bz2) get_filepath; tar xvjf "$file" ;; 450 | *.tar.gz) get_filepath; tar xvzf "$file" ;; 451 | *.tar.xz) get_filepath; tar xvJf "$file" ;; 452 | *.lzma) get_filepath; unlzma "$file" ;; 453 | *.bz2) get_filepath; bunzip2 "$file" ;; 454 | *.rar) get_filepath; unrar x -ad "$file" ;; 455 | *.gz) get_filepath; gunzip "$file" ;; 456 | *.tar) get_filepath; tar xvf "$file" ;; 457 | *.tbz2) get_filepath; tar xvjf "$file" ;; 458 | *.tgz) get_filepath; tar xvzf "$file" ;; 459 | *.zip) get_filepath; unzip "$file" ;; 460 | *.Z) get_filepath; uncompress "$file" ;; 461 | *.7z) get_filepath; 7z x "$file" ;; 462 | *.rar) get_filepath; unrar x "$file" ;; 463 | *.xz) get_filepath; unxz "$file" ;; 464 | *.exe) get_filepath; cabextract "$file" ;; 465 | *.deb) get_filepath; pkg unpack "$file" ;; 466 | *.rpm) get_filepath; pkg unpack "$file" ;; 467 | *.pet) get_filepath; pkg unpack "$file" ;; 468 | *.sfs) get_filepath; unsquashfs "$file" ;; 469 | *) false ;; 470 | esac 471 | # now move name/name/ to name/ 472 | archive_cleanup 473 | 474 | ) && continue 475 | done 476 | 477 | # else, check what we got by mime-type 478 | for f in $selected 479 | do 480 | case "$(file --mime-type -b "$f")" in 481 | image*) 482 | feh -Z -x -F -B black "$f" 483 | ;; 484 | audio*) 485 | ffplay -i "$f" -hide_banner -vn -nodisp -fast -autoexit -exitonkeydown \ 486 | || aplay -i "$f" 2>/dev/null 487 | ;; 488 | video*) 489 | mpv -fs -zoom "$f" 2>/dev/null \ 490 | || mplayer -fs -zoom "$f" 2>/dev/null \ 491 | || ffplay -i "$f" -fs -hide_banner -fast -autoexit 2>/dev/null 492 | ;; 493 | esac 494 | done 495 | fi 496 | 497 | done 498 | 499 | # if user exited properly, dont keep the search query 500 | rm /tmp/fzf/querytext 2>/dev/null 501 | 502 | --------------------------------------------------------------------------------