Ask Ubuntu is a question and answer site for Ubuntu users and developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I need to compare the user list (/etc/passwd) to a .csv file of account and get the account from /etc/passwd that are not in my csv file.

/etc/passwd shows:

root:x:0:0:root:/root:/bin/bash
albert:x:521:521:auto:/home/albert:/bin/bash
alfred:x:521:521:auto:/home/alfred:/bin/bash

.csv file shows:

albert,abc123

Expected output is:

root
alfred

I tried for 2 days with awk and grep but the result are not what I need..

share|improve this question
up vote 3 down vote accepted

A combination of grep, tr, cut and process substitution:

cut -d: -f1 /etc/passwd | grep -xvFf <(tr ',' '\n'  < file.csv)

The cut command gets the usernames from /etc/passwd (the first :-delimited field).

Then, the tr command converts your CSV fields to one username per line.

The grep command then looks for entire lines (-x) which don't match (-v) any fixed patterns (-F) from a file containing patterns, one per line (-f). We use process substitution (<()) to use tr's output for these patterns.

share|improve this answer
    
Thanks for that clear and smooth answer. Works like a charm ! – Alexander Feb 17 at 1:32
    
What could I do if I want to keep the same logic, but the expected output is: root:x:0:0:root:/root:/bin/bash alfred:x:521:521:auto:/home/alfred:/bin/bash (I would like to keep the whole line, because I have verification to do with the other information) – Alexander Feb 17 at 4:19
    
grep -wvFf <(tr ',' '\n' < file.csv) /etc/passwd, I suppose. – muru Feb 17 at 4:55

Not as smooth as muru's solution, but another way using comm, tr and cut and sort:

comm -13 <(<file tr ',' '\n' | sort) <(cut -d ':' -f 1 /etc/passwd | sort)
  • comm -13 <(<file tr ',' '\n' | sort) <(cut -d ':' -f 1 /etc/passwd | sort): compares the lines in the output of <file tr ',' '\n' | sort and cut -d ':' -f 1 /etc/passwd | sort and prints only the lines unique to cut -d ':' -f 1 /etc/passwd | sort;
  • <file tr ',' '\n' | sort: reads STDIN from file, translates commas to newlines and sorts the output file;
  • cut -d ':' -f 1 /etc/passwd | sort: prints the first colon-separated field of each line in /etc/passwd and sorts the output file;

And another way using combine (in the moreutils package: sudo add-apt-repository universe && sudo apt-get update && sudo apt-get install moreutils), which allows to save a couple of sort commands (though most likely combine sorts the files internally anyway):

combine <(cut -d ':' -f 1 /etc/passwd) NOT <(<file tr ',' '\n')
  • combine <(cut -d ':' -f 1 /etc/passwd) NOT <(<file tr ',' '\n'): compares the lines in the output of cut -d ':' -f 1 /etc/passwd and <file tr ',' '\n' and prints only the lines unique to cut -d ':' -f 1 /etc/passwd;
  • <file tr ',' '\n': reads STDIN from file and translates commas to newlines;
  • cut -d ':' -f 1 /etc/passwd: prints the first colon-separated field of each line in /etc/passwd;
share|improve this answer
    
Thanks you ! Also work like a charm and I just learned the 'comm' :) – Alexander Feb 17 at 1:34
    
ASking the same question I asked to Muru, if I want to output all the line of etc/shadow instead of the cut, how could I do with this command ? – Alexander Feb 18 at 0:13
    
@Alexander The solution muru gave you already is actually the best one I can think of, it should take care of almost all edge cases: askubuntu.com/questions/735576/…. – kos Feb 18 at 9:59
    
Thanks for all the help, I didn't notice his answer. – Alexander Feb 18 at 14:38

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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