Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

I have 2 sorted files produced by

xxx>find /store -type f -print | sort > /tmp/invent.txt
xxx>find /fbkup -type f -print | sort > /tmp/backup.txt

I want from diff a file name list of files missing in /store which are still on /backup, without any < > annotations, just one output file containing exactly the same records from /tmp/backup for which there was no match on /tmp/invent.txt.

xxx>diff -??? /tmp/invent.txt /tmp/invent.txt | xargs ...
share|improve this question

4 Answers 4

Diff your files, then use awk to find the lines you want (/^<), strip the leading bit (gsub(/^</,"")), and print the matched line.

diff file1 file2 | awk '/^</ {gsub(/^</,""); print}'

So if you want a one liner you could even do something like this.

diff <(cd /store ; find . -type f -print | sort) \
     <(cd /fbkup ; find . -type f -print | sort) | \
     awk '/^</ {gsub(/^</,""); print}'
share|improve this answer
1  
very good ! it probably wont get better than that until the author of comm adds a -n switch to negate the -1 and -2 option. –  Andreas Jan 18 '13 at 2:41

Don't use diff, use join instead. Since your input files are already sorted, the following should produce exactly the output you requested:

join -v 2 /tmp/invent.txt /tmp/backup.txt > /tmp/in-backup-but-not-invent.txt

(If the file paths in either /tmp/backup.txt or /tmp/invent.txt contain whitespace, then join may not work correctly with the options given above. In that case, you will have to look at using the -t option, to specify a non-whitespace char as the field separator for join. You would want to choose as field separator a char that does not actually appear in any of your file paths. Something like | or \ would probably suffice.)

share|improve this answer
    
Perfect, thanks !! –  Andreas Jan 19 '13 at 20:08
for i in `cat /tmp/invent.txt`; do grep ^$i$ /tmp/backup.txt >/dev/null || echo $i ; done

This will echo all names in /tmp/invent.txt which is not in /tmp/backup.txt

Edit

I found another way using diff :- (diff -r dir1 dir2)

-r, --recursive means Recursively compare any subdirectories found.

$ mkdir -p dir1/dir dir2/dir/dir

$ diff -r dir1 dir2
Only in dir2/dir: dir

$ touch dir1/file{a..d}

$ touch dir2/file{a..d}

$ touch dir2/dir/file{a..d}

$ echo hi >  dir2/filea

$ diff -q -r dir1 dir2
Only in dir2/dir: dir
Only in dir2/dir: filea
Only in dir2/dir: fileb
Only in dir2/dir: filec
Only in dir2/dir: filed
Files dir1/filea and dir2/filea differ
share|improve this answer
4  
clumsy... clumsy... 100,000 x 100,000 = 10 billion compares 1 –  Andreas Jan 18 '13 at 1:43
    
@Andreas see my edit. I found a more efficient way to compare directories. :) –  Suku Jan 18 '13 at 4:35
    
Thanks for trying to find a solution. See above, read my problem description, look how the 2 text files were obtained, aren't you solving another, very different problem? –  Andreas Jan 19 '13 at 20:26
    
Hmmm... Using diff -r you can find out the difference between two directories. Thats it. –  Suku Jan 20 '13 at 1:47

Diff can prolly do this, but im too lazy to check.

Try comm. comm -2 -3 or comm -1 -2 which'll give lines only in file A, or lines only in file B.

share|improve this answer
4  
This seems to be what he wants, but according to my manpage it looks like -1 and -2 turn OFF those outputs, not on. comm -23 turns off "lines unique to file 2" and "lines in both files" to print only lines in file 1 –  DerfK Jan 18 '13 at 1:44

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.