2010-04-23 71 views
112

我想寫一個簡單的腳本,列出兩個列表中找到的內容。爲了簡化,我們以ls爲例。想象一下,「一」和「二」是目錄。在Bash中的兩個列表的交集

 
one=`ls one` 
two=`ls two` 
intersection $one $two 

我仍然在bash中很綠,所以請隨時糾正我如何做到這一點。我只需要一些命令來打印出「一」和「二」中的所有文件。它們必須存在於兩者中。你可以稱之爲「一」和「二」之間的「交集」。

+0

這裏什麼都沒有回答這個問題:如何在Bash腳本中交叉兩個*變量*。 – jameshfisher 2014-09-20 20:43:42

+0

在我看來,這似乎是一個新問題,這個問題在這裏得到了明確的回答。 – 2014-09-25 11:58:28

+0

可以說是更有用的方法是在近似重複http://stackoverflow.com/questions/2312762/compare-difference-of-two-arrays-in-bash – tripleee 2016-06-30 07:52:43

回答

182
comm -12 <(ls 1) <(ls 2) 
+22

不能相信我直到今天都不知道'comm'。這只是讓我整整一週:) – 2014-08-19 17:49:38

+11

'comm'需要對輸入進行排序。在這種情況下,'ls'會自動對輸出進行排序,但其他用途可能需要這樣做:'comm -12 <(some-command | sort)<(某種其他命令|排序)' – 2015-01-15 21:11:11

+7

不要使用ls'輸出任何東西。 ls是交互式查看目錄元數據的工具。用代碼解析ls輸出的任何嘗試都被破壞了。 Globs更加簡單且正確: ''用於文件* .txt''。閱讀http://mywiki.wooledge.org/ParsingLs – 2016-01-25 03:49:55

27

使用comm命令:

ls one | sort > /tmp/one_list 
ls two | sort > /tmp/two_list 
comm -12 /tmp/one_list /tmp/two_list 

「排序」是不是真的需要,但爲了以防萬一使用「通訊」以前我總是包含它。

+4

它是很好的包括它,因爲它確實需要排序,他只用ls作爲例子。 – Thor84no 2012-02-28 11:47:50

2

效率較低(低於COMM)替代:

cat <(ls 1 | sort -u) <(ls 2 | sort -u) | uniq -d 
+1

如果你在使用Debian的/ bin/dash或其他非Bash shell你的腳本,你可以使用圓括號鏈接命令的輸出:'(ls 1; ls 2)| sort -u | uniq -d'。 – nitrogen 2014-10-08 20:19:46

+0

你正在描述union,而不是十字路口 – 2015-02-20 17:14:04

+1

@MikaëlMayer你應該標記這個人的名字你正在回答,否則它會被認爲是你的意思 – Benubird 2015-02-23 08:34:57

27

解決方案與comm

comm是偉大的,但確實需要排序名單的工作。幸運的是我們在這裏使用lsls猛砸男子頁

按字母排序,如果沒有-cftuSUX也不--sort的。

comm -12 <(ls one) <(ls two) 

替代與sort

交叉口兩個列表:

sort <(ls one) <(ls two) | uniq -d 

兩個列表的對稱差:

sort <(ls one) <(ls two) | uniq -u 

加成

播放它)

cd $(mktemp -d) && mkdir {one,two} && touch {one,two}/file_{1,2}{0..9} && touch two/file_3{0..9} 
+1

而不是補*,我認爲這就是通常所說的*對稱差*。 – 2016-01-28 00:00:22

1

加入是根據輸入另一個很好的選擇和所需的輸出

join -j1 -a1 <(ls 1) <(ls 2) 
-2

還有一個#1的問題「在bash陣列相交,」這被標記爲這個的重複。在我看來,這個問題並不完全一樣,因爲這個問題討論了比較兩個bash數組,而這個問題關注於bash文件。一個單行答案的其它問題,這是現在已經關閉,如下:

# List1=(0 1 2 3 4 6 7 8 9 10 11 12) 
# List2=( 1 2 3 5 6 8 9 11) 
# List3=($(comm -12 <(echo ${List1[*]}| tr " " "\n"| sort) <(echo ${List2[*]} | tr " " "\n"| sort)| sort -g)) 
# echo ${List3[*]} 
1 2 3 6 8 9 11 

的COMM實用程序的字母數字排序,而「在bash陣列交叉點」的答案使用數字;因此「排序」和「排序-g」的用法。