Bash-скрипт для отображения различий между двумя текстовыми файлами

Вы неправильно поняли, как работают жесткие ссылки. Нет оригинала. Все файлы просто жесткие ссылки на inode . Следовательно, жесткие ссылки на самом деле не ссылаются на файлы, они ссылаются на inodes.

Для иллюстрации рассмотрим следующий файл:

$ touch file
$ ls -li file
3282140 -rw-r--r-- 1 terdon terdon 0 May  3 16:27 file

Как видно выше, файл указывает на индексный дескриптор 3282140 . Теперь, если мы создадим мягкую ссылку на нее:

$ ln -s file softlink
$ ls -li 
3282140 -rw-r--r-- 1 terdon terdon 0 May  3 16:27 file
3282141 lrwxrwxrwx 1 terdon terdon 4 May  3 16:29 softlink -> file

Мягкая ссылка указывает на файл , но сама ссылка (которая также является объектом файловой системы, другим «файлом») имеет другой индексный дескриптор ( 3282141 ).Однако, если мы создадим жесткую ссылку, которая будет иметь один и тот же индексный дескриптор:

$ ln file hardlink
$ ls -li
total 0
3282140 -rw-r--r-- 2 terdon terdon 0 May  3 16:27 file
3282140 -rw-r--r-- 2 terdon terdon 0 May  3 16:27 hardlink
3282141 lrwxrwxrwx 1 terdon terdon 4 May  3 16:29 softlink -> file

Итак, если я теперь добавлю текст в жесткую ссылку , это будет точно так же, как если бы я добавил текст в файл . :

$ echo "foo" > hardlink 
$ cat hardlink 
foo
$ cat file
foo

И поскольку softlink указывает на файл , я увижу содержимое файла , если я cat ] it:

$ cat softlink 
foo

То же самое происходит, если я добавляю текст в файл , жесткая ссылка и файл эквивалентны:

$ echo bar >> file
$ cat hardlink 
foo
bar

Теперь, если я удалю ] файл , softlink будет неработающей ссылкой, но hardlink не будет затронут:

$ rm file 
$ ls -li
total 4
3282140 -rw-r--r-- 1 terdon terdon 8 May  3 16:33 hardlink
3282141 lrwxrwxrwx 1 terdon terdon 4 May  3 16:29 softlink -> file
$ cat softlink 
cat: softlink: No such file or directory

Поскольку цель ссылки была удалена, softlink поврежден. Жесткая ссылка, однако, все еще существует, поскольку указывала на тот же индексный дескриптор:

$ cat hardlink 
foo
bar

Все это означает, что просто нет способа отличить жесткую ссылку от файла, на который она была создана, потому что, в отличие от мягких ссылок, она на самом деле не был создан, указывающий на файл. Все файлы представляют собой жесткие ссылки, указывающие на индексный дескриптор файловой системы. Фактически, удаление файла просто удаляет ссылку на индексный дескриптор. Фактически он не удаляет данные. Система ведет подсчет ссылок, указывающих на каждый индексный дескриптор, и просто считает, что индексные дескрипторы доступны для записи, если количество ссылок равно 0.

Что вы можете сделать, так это найти все ссылки, указывающие на индексный дескриптор, и удалить все, кроме одной. Если мы вернемся туда, где мы были в начале:

$ rm *
$ touch file
$ ln file hardlink
$ ls -l file hardlink
-rw-r--r-- 2 terdon terdon 0 May  3 16:39 file
-rw-r--r-- 2 terdon terdon 0 May  3 16:39 hardlink
           ^
           |---- the number of links

Вывод ls -l включает количество ссылок, указывающих на индексный дескриптор.Следовательно, вы можете перебирать его вывод (это один из немногих случаев, когда синтаксический анализ ls безопасен) и удалять любые файлы с номером ссылки> 1:

for file in *; do [ $(ls -l $file | cut -d' ' -f2) -gt 1 ] && rm "$file"; done

Это удалит все жесткие ссылки, кроме одной, пока все жесткие ссылки находятся в одном каталоге.

Дополнительная литература: http://teaching.idallen.com/dat2330/04f/notes/links_and_inodes.html

4
26.09.2017, 23:23
2 ответа

Имея два отсортированных файла, commсделает это за вас.

См., например, комбинации параметров командной строки -2 -3и -1 -3.

3
27.01.2020, 20:55

Проверьте, работает ли он. Я могу добавить объяснение, если вам нужно.

awk '
/^$/{next}
FNR == NR {guest_2016[$1] = 1}
FNR != NR {
    if(!guest_2016[$1])
        print $1 > "new_guests.txt" 
    delete guest_2016[$1];
}
END {
    for(i in guest_2016)
        print i > "former_guests.txt"
}' guests-2016.txt guests-2017.txt
1
27.01.2020, 20:55

Теги

Похожие вопросы