So I know tools exist for this problem because I've heard about them, but I don't know what they are.

I want to do something like filter out all data but the usernames in /etc/passwd.

For example, I would want to grab user1, user2, and user3 from the following file. In this case, the logic could be "Grab text up to the first ':' on each line of the file".


The output would be:


cut exists for exactly this purpose. The -d flag specifies the delimiter, and -f specifies which fields to output:

cut -d: -f1 /etc/passwd

The argument to -f can be something like 1,3 to show the first and third fields, or 1-3 to show the first three; there are also -b and -c flags to read bytes and characters instead of fields. If you need something more flexible, generally awk will do the trick (see Matthew's answer)


Every time you want to extract data from a tabular input, you should consider awk. It is available on virtually every Unix system, so it's a good habit to take:

awk -F':' '{print $1}' /etc/passwd 
  • -F':': defines ":" as the column delimiter.
  • '{}': execute this instruction for each line.
  • print $1: print the first column to the screen.
  • 3
    Random note: awk takes a filename, so you can skip the pipe and just do awk -F: '{print $1}' /etc/passwd – Michael Mrozek Aug 30 '10 at 2:56
  • I always seem to forget that awk takes a filename, I always seem to use it in a pipeline...something like sed | awk etc... – Matthew Brannigan Aug 30 '10 at 14:39
  • almost everything that works with files take a filename (tr and at are a couple examples of the few things that don't). – Dennis Williamson Aug 30 '10 at 22:04

Here's a Perl one-liner:

perl -F/:/ -lane 'print $F[0]' /etc/passwd

Beneath perl and awk, there is a third tool for such jobs, which is sed:

sed 's/:.*//' FILE 

This is the substitution command: substitute from colon :, followed by a dot, which is a joker for characters of any kind, of any count (*), with nothing.

It is 's(ubstitute)/FROM/TO/' with TO being empty, which means 'delete everything from the first (since sed is by default greedy) colon (till end of line, since sed works well with entire lines).

Of course cut is a fine command as well, but I would say from a different family.


In your example, all 3 names are of the same length. In such cases - which might happen, but not so likely with /etc/passwd - you might use colrm too:

echo "user1:x:1:4
> user2:x:2:5
> user3:x:3:6" | colrm 6

or, of course

cat FILE | colrm 6 

(a rare case where useless use of cat doesn't apply, because you can't hand colrm a FILE to act on as parameter.)

  • cat is still useless there: colrm 6 < FILE. – manatwork Jun 28 '12 at 7:10
  • Well, yes, but not that useless, as in calling cat foo | grep bar. – user unknown Jun 28 '12 at 9:50

Just for completeness, there is no need for external commands, the shell (Bourne shell or compatible) can handle it alone:

while IFS=':' read -r needed garbage; do echo "$needed"; done < input_file

Of course, this is probably the slowest of all possible solutions, so for huge files pick another.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.