Skip to main content

1. Searching for files

  1. We can make a quick search for files with locate:

    locate bin/zip

    If the search requirement is not so simple, we can combine locate with other tools, like grep:

    locate zip | grep bin
    locate zip | grep bin | grep -v unzip
  2. While locate searches are based only on the file name, with find we can also make searches based on other attributes of files.

    It takes as arguments one or more directories that are to be searched:

    ls -aR ~
    find ~

    To find only directories we can use the option -type d and to find only files we can use -type f:

    find . -type d
    find . -type f
    find . -type d | wc -l
    find . -type f | wc -l
    find . | wc -l
  3. We can also search by filename and file size:

    sudo find /etc -type f | wc -l
    sudo find /etc -type f -name "*.conf" | wc -l

    We enclose the search pattern in double quotes to prevent shell from expanding "*".

    sudo find /etc -type f -name "*.conf" -size -2k | wc -l
    sudo find /etc -type f -name "*.conf" -size 2k | wc -l
    sudo find /etc -type f -name "*.conf" -size +2k | wc -l

    -2k matches the files whose size is less than 2 Kilobytes, 2k those who are exactly 2 Kilobytes, and +2k those who are more than 2 Kilobytes. Besides k we can also use M for Megabytes, G for Gigabytes, etc.

  4. find supports many other tests on files and directories, like the time of creation or modification, the ownership, permissions, etc. These tests can be combined with logical operators to create more complex logical relationships. For example:

    find ~ \( -type f -not -perm 0600 \) -or \( -type d -not -perm 0700 \)

    This looks weird, but if we try to translate it to a more understandable language it means: find on home directory ( files with bad permissions ) -or ( directories with bad permissions ). We have to escape the parentheses to prevent shell from interpreting them.

  5. We can also do some actions on the files that are found. The default action is to -print them to the screen, but we can also -delete them:

    touch test{1,2,3}.bak
    ls
    find . -type f -name '*.bak' -delete
    ls
    touch test{1,2,3}.bak
    find . -type f -name '*.bak' -print -delete
    ls

    We can also execute custom actions with -exec:

    touch test{1,2,3}.bak
    ls
    find . -name '*.bak' -exec rm '{}' ';'
    ls

    Here {} represents the pathname that is found and ; is required to indicate the end of the command. Both of them have been quoted to prevent shell from interpreting them.

    If we use -ok instead of -exec then each command will be confirmed before being executed:

    touch test{1,2,3}.bak
    ls
    find . -name '*.bak' -ok rm '{}' ';'
  6. Another way to perform actions on the results of find is to pipe them to xargs, like this:

    touch test{1,2,3}.bak
    ls
    find . -name '*.bak' | xargs echo
    find . -name '*.bak' | xargs ls -l
    find . -name '*.bak' | xargs rm
    ls

    xargs gets input from stdin and converts it into an argument list for the given command.

Loading asciinema cast...