Спосіб 1: використовуйте те, що знаєте
Оскільки ви вже знаєте, як здійснювати циклічність на одному файлі, ви можете комбінувати файли та обробляти комбіновані файли. Команда paste
з'єднує два файли по черзі. Він ставить вкладку між рядками, що надходять з двох файлів, тому це рішення передбачає, що в назвах файлів немає вкладок. (Ви можете змінити роздільник, але вам потрібно знайти символ, який не присутній у імені файлу.)
paste -- "$list1.txt" "list2.txt" |
while IFS=$'\t' read -r file1 file2 rest; do
diff -q -- "$file1" "$file2"
case $? in
0) status='same';;
1) status='different';;
*) status='ERROR';;
esac
echo "$status $file1 $file2"
done
Якщо ви хочете пропустити порожні рядки, вам потрібно зробити це у кожному файлі окремо, оскільки він paste
може відповідати порожньому рядку з одного файлу та непустому рядку з іншого файлу. Ви можете використовувати grep
для фільтрації порожніх рядків.
paste -- <(grep '[^[:space:]]' "$list1.txt") <(grep '[^[:space:]]' "list2.txt") |
while IFS=$'\t' read -r file1 file2 rest; do
…
Зауважте, що якщо два файли мають різну довжину, ви отримаєте порожній $file2
(незалежно від того, який список закінчився першим).
Спосіб 2: петля на два файли
Ви можете поставити настільки складну команду, як вам подобається, за умови циклу while. Якщо поставити, read file1 <&3 && read file2 <&4
то цикл буде працювати до тих пір, поки в обох файлах є рядок для читання, тобто поки не закінчиться один файл.
while read -u 3 -r file1 && read -u 4 -r file2; do
…
done 3<list1..txt 4<list2.txt
Якщо ви хочете пропустити порожні рядки, це трохи складніше, тому що вам потрібно зробити пропуск у двох файлах самостійно. Найпростіший спосіб - розбити проблему на дві частини: пропустити порожні рядки з одного файлу та обробити непорожні рядки. Один з способів пропустити порожні рядки - це обробка, grep
як описано вище. Слідкуйте за необхідним пробілом між <
оператором перенаправлення та тим, <(
що запускає командний підбір.
while read -u 3 -r file1 && read -u 4 -r file2; do
…
done 3< <(grep '[^[:space:]]' "$list1.txt") 4< <(grep '[^[:space:]]' "list2.txt")
Інший метод - записати функцію, яка поводиться так, read
але пропускає порожні рядки. Ця функція може працювати, викликаючи read
цикл. Це не повинно бути функцією, але функція є найкращим підходом як до організації коду, так і тому, що цей фрагмент коду потрібно викликати двічі. У функції ${!#}
- екземпляр конструкції bash, ${!VARIABLE}
який оцінює значення змінної, ім'я якої - значення VARIABLE
; тут змінна - це спеціальна змінна, #
яка містить кількість позиційного параметра, так само ${!#}
є останнім позиційним параметром.
function read_nonblank {
while read "$@" &&
[[ ${!#} !~ [^[:space:]] ]]
do :; done
}
while read_nonblank -u 3 -r file1 && read_nonblank -u 4 -r file2; do
…
done 3<list1..txt 4<list2.txt
diff
.