Linux commands every user should master
When it comes to linux, there are some commands that you can't live without and
then there are some you shouldn't live without. I mean sure, you can live your
life without ever using grep or find but you'd never believe how much
productive knowing a few more terminal commands can make you.
Here is a list of the commands we are going to take a look at:
- man
- grep
- find
- sed
The command that started it all: man
I really hope you know this one. But in case you don't, well today is your
lucky day. This command is really special because it will, from today onwards
be your first guide to using any terminal command. man stands for
manual and is literally your handbook of linux commands. Any time you are
wondering how to use a command, sed for example, open up your terminal and
type
man <command>
or as in this case,
man sed
and it will give you a quick summary of what the command is, and how to use
it. There isn't anything more than that to it, yet I use it multiple times
everyday when I forget the syntax of chmod command or have forgotten how
the bash time command is different from that packaged with zsh.
Search through files, content, outputs, basically anything: grep
This one is basically a search command. But unlike the upcoming find command,
this one doesn't search for just the names of files. It searches through their
content as well. Not only that, it is also super handy when you have to filter
out lines that contain some specific content from let's say a huge output from
previous command. This command takes getting some used to, but after some time,
you wouldn't even believe you used to be able to get any work without it. Let's
start, shall we?
Content from files
Let's say you want to search for any files in which you have TODO written inside (as in code comments maybe?) also, you want the search to be case insensitive and search all subfolders of current folder too (recursively). You'd write:
grep -i -r TODO .Now, I suggest you look up the flags (those dash followed by characters) I used in the above command using
man grep. I will still tell you in case you don't have a means to run themancommand right now.The
-iflag is for case-insensistive search.The
-rsearches sub-folders recursively.TODOis the phrase we want to search for. You can even use regex expressions (which is where the true power lies), and that seems to be true for many linux commands you'll learn in future..is the usual symbol for current directory...can be used for parent directory, or a directory name can be given, relative to the current directory.Content from stdin or pipe
If the last parameter
file or folder name to searchin previous command is not provided, thengreptries to search instdin. Now, that doesn't mean you actually have to type the content, but being able to take content from stdin allows grep to use something much more useful in linux - pipes! What a pipe or|does is that it sends the output of one command as stdin to another. Thus, a command like:ls | grep -i txtwill execute
lsand then take that output and give it togrep. Now grep will execute its search on this content (output ofls). Thus, in above example, it will search for lines that will have txt in them.
The plain old but much more powerful than you thought find command
The find command is one of the most used commands in Linux.
find command is used to search and locate list of files and directories
matching arguments you specify. find can be used in variety of conditions
with its various flags to find files by permissions, users, groups, file type,
date, size and other possible criteria. The format for the find command is a
little unintuitive for those with a habit of using grep or ag. Like always,
I'd advice you to read the man page for find using man find command.
Files by their name
To find a file by its name, just use the following format:
find <directory> -name <name>So, if you want to search for a file named
abc.txtin current directory, you can dofind . -name "abc.txt"or
find . -name "*.txt"to find all files ending with
.txtNote that the only compulsory argument is the directory name. The
-nameis just to filter the files by name. And as you may have guessed, there are a lot more filters at your disposal. This will also search all sub-directories in the current folder recursively.Files using advanced filters
Let's look at the following command:
find -maxdepth 4 -amin +3 -iname "PaLLaV" -size -4M -type f -user rootThis is an example of how multiple filters can be chained up to create an advanced search.
-maxdepth 4will go at max 4 levels down (in subdirectories) while searching.-amin +3will keep only those files that were last accessed more than 3 minutes ago (notice the+in+3).-iname "PaLLaV"will search for files with namepallavWITHOUT caring about case sensitivity (-namewould've been case sensitive).-size -4Mwill only choose those results that are less than 4MegaBytes because of-in-4M.-type fwill filter out the files and ignore the directories.-user rootwill only give out the files that are owned byroot.
As you may have guessed, these are not the only filters you can use. There are actually tons more. You can literally phrase the command to find any file you lost on your hard drive and only remember vague details about.
The stream editor with all powers of an editor: sed
I know I promised you a tutorial of sed, but the fact is, there is no way I
can do justice to its power in a few paragraphs. So, instead I'm going to refer
you to this tutorial. It's long,
but I really recommend you go through the starting parts. sed has terrible
documentation and man sed doesn't help a lot in this case, because just
knowing the format of commands doesn't bring out its power at all. If you aren't
sold yet, I'll give you an easy example of sed usage. Let's say you ran
ifconfig and got the output:
enp9s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.24.8.63 netmask 255.255.255.255 broadcast 172.24.8.63
inet6 fe80::f276:1cff:fe0b:b377 prefixlen 64 scopeid 0x20<link>
ether f0:76:1c:0b:b3:77 txqueuelen 1000 (Ethernet)
RX packets 2578393 bytes 3323277819 (3.0 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1368479 bytes 189953405 (181.1 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 0 (Local Loopback)
RX packets 529 bytes 1361550 (1.2 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 529 bytes 1361550 (1.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
but you just want the output to be type followed by ip addr, for every ip address as in:
inet 172.24.8.63
netmask 255.255.255.255
broadcast 172.24.8.63
inet 127.0.0.1
netmask 255.0.0.0
Let's try to make the output like that:
First grep to filter out the lines that have IP addresses.
ifconfig | grep -P "(\d{1,3}\.){3}\d{1,3}"Couple of things to note: The
-Pis for using perl type regex. This allows us to use\dfor digits, in sed we'll still have to use[0-9]as\dformat isn't supported. Then we say that there will be atleast 1 and at most 3 digits{1,3}. Then it will be followed by a dot\.. Read up on regex if you don't know why the dot has been preceded by a\. Then this whole group (digits and dot) is repeated exactly 3 times, followed by another group of 1-3 digits.This filters out the lines with IP addresses as in:
inet 172.24.8.63 netmask 255.255.255.255 broadcast 172.24.8.63 inet 127.0.0.1 netmask 255.0.0.0Now we use sed to add newlines after every IP address.
sed -r "s|([0-9]{1,3}\.){3}[0-9]{1,3}|\0\n|g"Now, the
-ris to use extended regular expressions.sis for substitute command.|is the separator (can be anything not used in the substitution pattern). This is followed by the same regex expression as before, but instead of\dwe have used[0-9]as\disn't supported bysed. Then we use another separator|. Then we have the substitution content.\0just puts the whole pattern that was matched. This is needed as we do not want to delete the original content. The\nis for a newline. The|gis another separator followed byglobalwithout which only the first match in every line will be replaced. Now the output is:inet 172.24.8.63 netmask 255.255.255.255 broadcast 172.24.8.63 inet 127.0.0.1 netmask 255.0.0.0Unfortunately, the formatting doesn't look too good.
Let's add a new sed command to eat all the beginning spaces:
sed -r "s|^ *||"This one's easy, by using
^, we are substituting for all the spaces in the beginning of the line and replacing with nothing. This gives us the final output:inet 172.24.8.63 netmask 255.255.255.255 broadcast 172.24.8.63 inet 127.0.0.1 netmask 255.0.0.0
Note, our final command thus will be:
ifconfig | grep -P "(\d{1,3}\.){3}\d{1,3}" | sed -r
"s|([0-9]{1,3}\.){3}[0-9]{1,3}|\0\n|g" | sed -r "s|^ *||"
and while this might seem like too much work, think about how much you'd have to write if you were to create a script to do these transformations using C++ or python. These commands allow creation of really clean and compact scripts (OK, maybe just compact scripts).
Now, that you know the secrets, get cracking!
I hope you enjoyed reading this post.
Consider sharing this article using the links below.