Today we’ll look at how you find files, and text inside these files, quickly and efficiently.
It can be very frustrating to know that a file or setting exists, but not be able to track it down! Master today’s commands and you’ll be much more confident as you administer your systems.
Today you’ll look at four useful tools:
locate
find
grep
which
If you're looking for a file called access.log
then the quickest approach is to use "locate" like this:
$ locate access.log
/var/log/apache2/access.log
/var/log/apache2/access.log.1
/var/log/apache2/access.log.2.gz
(If locate
is not installed, do so with sudo apt install mlocate
)
As you can see, by default it treats a search for "something" as a search for "*something*". It’s very fast because it searches an index, but if this index is out of date or missing it may not give you the answer you’re looking for. This is because the index is created by the updatedb
command - typically run only nightly by cron
. It may therefore be out of date for recently added files, so it can be worthwhile updating the index by manually running: sudo updatedb
.
The find
command searches down through a directory structure looking for files which match some criteria - which could be name, but also size, or when last updated etc. Try these examples:
find /var -name access.log
find /home -mtime -3
The first searches for files with the name "access.log", the second for any file under /home
with a last-modified date in the last 3 days.
These will take longer than locate
did because they search through the filesystem directly rather from an index. Also, because find
uses the permissions of the logged-in user you’ll get “permission denied” messages for many directories if you search the whole system. Starting the command with sudo
of course will run it as root - or you could filter the errors with grep
like this: find /var -name access.log 2>&1 | grep -vi "Permission denied"
.
These examples are just the tip of a very large iceberg, check the articles in the RESOURCES section and work through as many examples as you can - time spent getting really comfortable with find
is not wasted.
Rather than asking "grep" to search for text within a specific file, you can give it a whole directory structure, and ask it to recursively search down through it, including following all symbolic links (which -r
does not).
This trick is particularly handy when you "just know" that an item appears "somewhere" - but are not sure where.
As an example, you know that “PermitRootLogin” is an ssh parameter in a config file somewhere under /etc, but can’t recall exactly where it is kept:
grep -R -i "PermitRootLogin" /etc/*
Because this only works on plain text files, it's most useful for the /etc
and /var/log
folders. (Notice the -i
which makes the search “case insensitive”, finding the setting even if it’s been entered as “Permitrootlogin”
You may now have logs like /var/log/access.log.2.gz
- these are older logs that have been compressed to save disk space - so you can't read them with less
, or search them with grep
. However, there are zless
and zgrep
, which do work, and on ordinary as well as compressed files.
It's sometimes useful to know where a command is being run from. If you type nano
, and it starts, where is the nano
binary coming from? The general rule is that the system will search through the locations setup in your "path". To see this type:
echo $PATH
To see where nano
comes from, type:
which nano
Try this for grep
, vi
and service
and reboot
. You'll notice that they’re typically always in subfolders named bin
, but that there are several different ones.
The "-exec" feature of the "find" command is extremely powerful. Test some examples of this from the RESOURCES links.
Copyright 2012-2021 @snori74 (Steve Brorens). Can be reused under the terms of the Creative Commons Attribution 4.0 International Licence (CC BY 4.0).