Учитывая два дерева каталогов, как определить, какие имена файлов одинаковы, учитывая только имена файлов, удовлетворяющие условию?

Этот ответ подсказывает, как найти файлы с тем же именем в двух каталогах в bash:

diff -srq dir1/ dir2/ | grep identical 

Теперь я хочу рассмотреть файлы, которые удовлетворяют условию. Если я использую ls E* , я возвращаю файлы, начиная с E. Я хочу сделать то же самое с приведенной выше командой: дайте мне имена файлов, которые различаются в dir1/ и dir2/ , но учитывайте только те, которые начинаются с E.

Я попробовал следующее:

 diff -srq dir1/E* dir2/E* | grep identical 

но это не сработало, я получил этот результат:

diff: extra operand ‘/ home / pal / konkoly / c6 / elesbe3 / 1 / EPIC_212291374- c06-k2sc.dat.flag.spline’ diff: Try ‘diff –help’ для получения дополнительной информации.

(( /home/pal/konkoly/c6/elesbe3/1/EPIC_212291374- c06-k2sc.dat.flag.spline является файлом в так называемом dir1 , но EPIC_212291374- c06-k2sc.dat.flag.spline не является в так называемом dir2 ))

Как я могу это решить?


Я попытался сделать это следующим образом, исходя из этого ответа :

 DIR1=$(ls dir1) DIR2=$(ls dir2) for i in $DIR1; do for j in $DIR2; do if [[ $i == $j ]]; then echo "$i == $j" fi done done 

Он работает, как указано выше, но если я пишу DIR1=$(ls path1/E*) и DIR2=$(ls path2/E*) , это не так, я не получаю никакого вывода.

Это не проверено, но я бы попробовал что-то вроде:

 comm -12 < (cd dir1 && ls E*) <(cd dir2 && ls E*) 

Основная идея:

  • Создайте список имен файлов в dir1 которые удовлетворяют нашему условию. Это можно сделать с помощью ls E* потому что мы имеем дело только с плоским списком файлов. Для подкаталогов и рекурсии мы будем использовать find вместо этого (например, find . -name 'E*' -type f ).

  • Поместите имена файлов в каноническом порядке (например, путем сортировки их). Здесь мы ничего не должны делать, потому что E* все равно расширяется в отсортированном порядке. С помощью find нам, возможно, придется сначала вывести вывод в sort .

  • Сделайте то же самое с dir2 .

  • Только выходные линии, которые являются общими для обоих списков, которые могут быть выполнены с помощью comm -12 .

    comm ожидает, что будет передано два имени файла в командной строке, поэтому мы используем функцию bash < ( ... ) для создания subprocessа и подключения его вывода к именованному каналу; имя трубы можно передать в comm .

Принятый ответ работает отлично. Хотя, если кому-то нужна реализация python, это также работает:

 import glob dir1withpath=glob.glob("path/to/dir1/E*") dir2withpath=glob.glob("path/to/dir2/E*") dir1=[] for index,each in enumerate(dir1withpath): dir1list=dir1withpath[index].split("/") dir1.append(dir1list[-1]) dir2=[] for index,each in enumerate(dir2withpath): dir2list=dir2withpath[index].split("/") dir2.append(dir2list[-1]) for each1 in dir1: for each2 in dir2: if each1 == each2: print(each1 + "is in both directories")