Пересечение двух списков в Bash

Я пытаюсь написать простой скрипт, который будет перечислять содержимое, найденное в двух списках. Чтобы упростить, давайте использовать ls в качестве примера. Представьте, что "один" и "два" являются каталогами.

один =`лс один`
two=`ls two`
пересечение $ один $ два

Я все еще довольно зеленый в Bash, так что не стесняйтесь исправить, как я это делаю. Мне просто нужна команда, которая распечатает все файлы в "один" и "два". Они должны существовать в обоих. Вы можете назвать это "пересечением" между "один" и "два".

6 ответов

Решение
comm -12  <(ls 1) <(ls 2)

Решение сcomm

comm это здорово, но действительно нужно работать с отсортированным списком. И, к счастью, здесь мы используем ls который из ls Страница руководства Bash

Сортируйте записи по алфавиту, если ни -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}

Использовать comm команда:

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

"sort" на самом деле не нужен, но я всегда включаю его перед использованием "comm" на всякий случай.

Менее эффективная (чем комм) альтернатива:

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

Присоединение является еще одним хорошим вариантом в зависимости от ввода и желаемого результата

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

Есть еще один вопрос Stackru "Пересечение массива в 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" отвечает числами; отсюда использование "sort" и "sort -g".

Другие вопросы по тегам