Skip to content
suewonjp edited this page Feb 5, 2023 · 8 revisions

lf - Quickly type and search files

lfi - Same as lf except that case insensitive matching is performed

✔️ General Usages

  1. lf [ file pattern ]
    • Will search every file matching the given [file pattern] through the current working directory
    • By default, dot folders (like .git, .svn, etc) will be ignored
      • In order to include dot folders, use .+ notation. (See below)
    • e.g) lf .txt
  2. lf [ base dir ] [ (optional) intermediate patterns ... ] [ file pattern ]
    • Will search every file matching the given patterns through the given [base dir]
    • IMPORTANT! : [base dir] should be a complete path name, not a partial matching pattern
    • If [base dir] doesn't exist on the file system, the search will fail
    • e.g) lf doc .pdf
      • Notice that the [intermediate pattern] doc may be part of the filename or intermediate directory names
      • For example, it may match document.pdf or docs/ebook.pdf or somedir/docs/ebook.pdf
    • e.g) lf src web home .js
    • e.g) lf ~/bin .sh
    • e.g) lf /usr/local share .txt
  3. lf --help
    • Will show help message

✔️ Special Notations

  • -- Notation
    • Denotes arbitrary files
    • lf requires [file pattern] to be specified as its last parameter
    • But sometimes you have no clue about patterns of target files
    • Or you may want to list all files involved with certain directory patterns
    • In these cases, you can use -- to denote any arbitrary file
    • e.g) lf . src main --
      • Will search arbitrary files with pattern *src*main* through current working directory.
      • It may match src/main/foo.java or src/main.java or foo/src/bar/main/baz.txt, etc.
  • + Notation
    • Directs lf to list the output as absolute path
    • e.g) lf + doc .pdf
      • Will recursively search .pdf files through current working directory so that matching files should contain the pattern *doc*.pdf;
      • The output results will be absolute path
    • e.g) lf +doc .pdf
      • Will recursively search .pdf files through $PWD/doc directory
      • The output results will be absolute path
  • .+ Notation
    • Will also search through dot folders (such as .git, .svn, .vim, etc)
    • Without this notation used, lf will exclude dot folders from its search
    • e.g) lf .+ .java
      • Will search .java files through current working directory including dot folders
    • e.g) lf .+src .java
      • Will search .java files through src directory and include any of dot folders under that directory
    • Notice that lf still ignores some widely known dot folders even if .+ notation is used. See _LIST_FILE_DIRS_IGNORE variable section below
  • +.+ Notation
    • Same as .+ except that the output results will be absolute path
    • Notice that this notation cannot be attached to [base dir] like + and .+ do
      • e.g) You can't use like lf +.+src --

✔️ Quick Behavioral Control Variables

Available Since Version 0.7

  • ignore variable : Use it to specify folders to ignore

    • e.g) ignore=node_module lf .js
    • Use colon (:) to specify multiple folders to ignore.
      • e.g) ignore=node_module:www lf .js
    • Quote them if they contain space characters.
      • e.g) ignore='node_module:temp memo' lf .js
  • append variable : Append new search result to the existing search result.

    • Search result of lf is cached and you can access that cache using lfs or lff

    • Every run of lf will overwrite this cache but if you use append variable, the new result will be appended to that cache.

    • You don't have to assign value to append variable.

        $ lf .js
      
        foo.js
        bar.js
      
        $ append= lf .txt
      
        foo.js
        bar.js
        baz.txt
      
  • prepend variable : Similar to append but it will prepend the new result to the existing result.

    • If append and prepend are used simultaneously (mostly, pointless, though), only prepend will be respected.
  • pre and post ( Available Since Version 0.8 )

    • Specify some prefix using pre and some postfix using post

    • Also can be used for lfs or lff

        $ pre='( ' post=' )' lf .js
      
        ( foo.js )
        ( bar.js )
      
  • q or qq ( Available Since Version 0.8 )

    • q is a shortcut for pre=\' post=\' and pp is a shortcut for pre=\" post=\"

    • Also can be used for lfs or lff

        $ q= lf .js
      
        'foo.js'
        'bar.js'
      
        $ qq= lf .js
      
        "foo.js"
        "bar.js"
      
  • nul ( Available Since Version 0.8 )

    • Use nul byte as the separator instead of new line character

    • Useful when you have a filename containing spaces or new line characters

    • Also can be used for lfs or lff

        $ nul= lf .js | while read -d $'\0' f; do
            cp "$f" "$f.bak"
        done
      
        $ nul= lfs | xargs -0 rm
      
  • del ( Available Since Version 0.8 )

    • Delete files/folders found by lf or lfi or lfs or lff

    • It uses rmrf command to delete files/folders

        $ del= lf .js
      
        lf.sh : Are you sure if you want to delete the following path? (y or n)
            foo.js
            bar.js
        y
        lf.sh : "foo.js" (file) deleted...
        lf.sh : "bar.js" (file) deleted...
      
  • sym ( Available Since Version 0.9 )

    • Search files through symlinks

    • ( lf follows symlinks by default since version 1.0.0, but previous versions don't )

    • It'll work for g, too.

        $ tree -a test
      
        test
        ├── baz.lst
        ├── database -> ../database
        └── log
            └── error.log
      
        ### 'database' is not a folder. It's a symlink
      
        $ lf test --      ### Don't follow symlinks by default.
      
        test/baz.lst
        test/database/civilizer.h2.db
        test/log/error.log
      
        $ sym=no lf test -- ### Don't follow symlinks.
      
        test/baz.lst
        test/log/error.log
      

You can configure names of Behavior Control Variables ( Available Since Version 0.8 )
Refer to this

✔️ _LIST_FILE_DIRS_IGNORE variable

lf will ignore the following dot folders whether or not you use .+ or +.+ notations.

    .git, .svn, .hg

Because the content of these well known version control data folders are of no interest to most people.

However, if you want to search through these folders for whateve reason or you want to add additional folders to ignore, you can do that by setting _LIST_FILE_DIRS_IGNORE environment variable.

To make lf not to ignore any folder when you use .+ or +.+ notations, use:
( Notice that colon at the end! )

    _LIST_FILE_DIRS_IGNORE=:

To add additional folders to ignore by default, set it like so:
( Assume you want to ignore .vim folder in addition to the default folders above )

    _LIST_FILE_DIRS_IGNORE=.git:.svn:.hg:.vim

Notice that : (colon) is used as the delimiter, so you can specify folder names containing spaces.

✔️ Quirks

  • Avoid using a separate asterisk (*) like lf doc work *
    • This won't work and may produce unexpected results
    • Most shells including Bash will execute pathname expansion when they see wildcards such as * and if * is used alone (which is most greedy), it will be expanded every path name under the current working directory
    • This behavior is based on POXIS specification and there is little lf.sh can do about it
    • Though, concatenating * to other patterns will be OK like lf doc work important*.pdf
    • However, even in this case, a space is preferable to *
      • e.g) lf doc work important .pdf is equivalent to lf doc work important*.pdf
    • If your intention is to denote arbitrary files, then use -- notation instead:
      • lf doc work * => BAD (X)
      • lf doc work -- => GOOD (O)
  • Be careful when [base dir] is an absolute path, because the search will highly likely take forever
    • Avoid the following usages:
      • lf ~ bin .sh => BAD (X)
      • lf / usr local bin -- => BAD (X)
    • Specify a more concrete base directory as follows:
      • lf ~/bin .sh => GOOD (O)
      • lf /usr/local bin -- => GOOD (O)

✔️ Tips

  • Using / to denote folder patterns may help
    • Consider lf doc today important .pdf; This may match all of the following files:
      • doc/work/today-important-work.pdf ( today matching a file name)
      • doc/today/important-task.pdf ( today matching a folder name)
    • If you want to match today with an intermediate folder name, then use lf doc today/ important .pdf
  • When you want to select only a single path from multiple paths returned from lf or lfi, then use lfs or lff
    • Remember that these commands have a feature of copying the obtained path to the system clipboard so that you can easily use that path for other applications
    • See lfs or lff for more details
  • When you want to grep text using syntax of lf, then use g or gi
    • e.g) g [Jj]ava . e-book .txt Will grep text using pattern [Jj]ava from files returned by lf . e-book .txt
  • Here are more tips