Fuzzy file search in linux console

爱⌒轻易说出口 提交于 2019-11-27 10:45:13

问题


Does anybody know a way to perform a quick fuzzy search from linux console?

Quite often I come accross situation when I need to find a file in a project but I don't remember the exact filename. In Sublime text editor I would press Ctrl-P and type a part of the name, which will produce a list of the files to select from. That's an amazing feature I'm quite happy with. The problem is that in most cases I have to browse a code in a console on remote machines via ssh. So I'm wondering is there a tool similar to "Go Anywhere" feature for Linux console?


回答1:


You may find fzf useful. It's a general purpose fuzzy finder written in Go that can be used with any list of things: files, processes, command history, git branches, etc.

Its install script will setup CTRL-T keybinding for your shell. The following GIF shows how it works.




回答2:


The fasd shell script is probably worth taking a look at too.

fasd offers quick access to files and directories for POSIX shells. It is inspired by tools like autojump, z and v. Fasd keeps track of files and directories you have accessed, so that you can quickly reference them in the command line.

It differs a little from a complete find of all files, as it only searches recently opened files. However it is still very useful.




回答3:


Most of these answers won't do fuzzy searching like sublime text does it -- they may match part of the answer, but they don't do the nice 'just find all the letters in this order' behavior.

I think this is a bit closer to what you want. I put together a special version of cd ('fcd') that uses fuzzy searching to find the target directory. Super simple -- just add this to your bashrc:

function joinstr { local IFS="$1"; shift; echo "$*"; }
function fcd { cd $(joinstr \* $(echo "$*" | fold -w1))* }

This will add an * between each letter in the input, so if I want to go to, for instance,

/home/dave/results/sample/today

I can just type any of the following:

fcd /h/d/r/spl/t
fcd /h/d/r/s/t
fcd /h/d/r/sam/t
fcd /h/d/r/s/ty

Using the first as an example, this will execute cd /*h*/*d*/*r*/*s*p*l*/*t* and let the shell sort out what actually matches.

As long as the first character is correct, and one letter from each directory in the path is written, it will find what you're looking for. Perhaps you can adapt this for your needs? The important bit is:

$(joinstr \* $(echo "$*" | fold -w1))*

which creates the fuzzy search string.




回答4:


I usually use:

ls -R | grep  -i [whatever I can remember of the file name]

From a directory above where I expect the file to be - the higher up you go in the directory tree, the slower this is going to go.

When I find the the exact file name, I use it in find:

find . [discovered file name]

This could be collapsed into one line:

for f in $(ls --color=never -R | grep --color=never -i partialName); do find -name $f; done

(I found a problem with ls and grep being aliased to "--color=auto")




回答5:


find . -iname '*foo*'

Case insensitive find of filenames containing foo.




回答6:


I don't know how familiar you are with the terminal, but this could help you:

find | grep 'report'
find | grep 'report.*2008'

Sorry if you already know grep and were looking for something more advanced.




回答7:


You can do the following

grep -iR "text to search for" .

where "." being the starting point, so you could do something like

grep -iR "text to search" /home/

This will make grep search for the given text inside every file under /home/ and list files which contain that text.




回答8:


fd is a simple, fast and user-friendly alternative to find.

Demo from the GitHub project page:




回答9:


You can try c- (Cminus), a fuzzy dir changing tool of bash script, which using bash completion. It is somehow limited by only matching visited paths, but really convenient and quite fast.

GitHub project: whitebob/cminus

Introduction on YouTube: https://youtu.be/b8Bem53Cz9A




回答10:


You might want to try AGREP or something else that uses the TRE Regular Expression library.




回答11:


You could use find like this for complex regex:

find . -type f -regextype posix-extended -iregex ".*YOUR_PARTIAL_NAME.*" -print

Or this for simplier glob-like matches:

find . -type f -name "*YOUR_PARTIAL_NAME*" -print

Or you could also use find2perl (which is quite faster and more optimized than find), like this:

find2perl . -type f -name "*YOUR_PARTIAL_NAME*" -print | perl

If you just want to see how Perl does it, remove the | perl part and you'll see the code it generates. It's a very good way to learn by the way.

Alternatively, write a quick bash wrapper like this, and call it whenever you want:

#! /bin/bash
FIND_BASE="$1"
GLOB_PATTERN="$2"
if [ $# -ne 2 ]; then
    echo "Syntax: $(basename $0) <FIND_BASE> <GLOB_PATTERN>"
else
        find2perl "$FIND_BASE" -type f -name "*$GLOB_PATTERN*" -print | perl
fi

Name this something like qsearch and then call it like this: qsearch . something



来源:https://stackoverflow.com/questions/9439121/fuzzy-file-search-in-linux-console

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!