2009-07-25 09:41:26 +0000 2009-07-25 09:41:26 +0000
104
104

Как вы можете увидеть реальную жесткую ссылку на ls?

Я запускаю

ln /a/A /b/B

Хочу посмотреть в папке a, где файл A указывает на ls.

Ответы (9)

182
182
182
2009-07-25 10:01:32 +0000

Вы можете найти номер inode для вашего файла с

ls -i

и

ls -l

показывает количество ссылок (количество жестких ссылок на определенный inode)

после того, как вы нашли номер inode, вы можете искать все файлы с одним и тем же inode:

find . -inum NUM

покажет имена файлов для inode NUM в текущем каталоге (.)

66
66
66
2009-07-25 09:51:57 +0000

На ваш вопрос нет четкого ответа. В отличие от сим-ссылок, жесткие ссылки неотличимы от “исходного файла”. Записи в каталоге

состоят из имени файла и указателя на вход. Внутренний код, в свою очередь, содержит метаданные файла и (указатель на) фактическое содержимое файла). При создании жесткой ссылки создается другое имя файла + ссылка на тот же вход. Эти ссылки однонаправленные (по крайней мере, в типичных файловых системах) – в иноде хранится только счетчик ссылок. Нет внутреннего способа узнать, что является “оригинальным” именем файла.

Кстати, поэтому системный вызов для “удаления” файла называется unlink. Он просто удаляет жесткую ссылку. Входящие данные удаляются только в том случае, если счетчик ссылок на входе падает до 0.

Единственный способ найти остальные ссылки на данный вход - исчерпывающий поиск по файловой системе, проверяющей, какие файлы относятся к данному входу. Вы можете использовать ‘test A -ef B’ из оболочки для выполнения этой проверки.

24
24
24
2009-07-25 10:01:38 +0000
ls -l

Первый столбец будет представлять разрешения. Вторая колонка будет представлять количество подпунктов (для каталогов) или количество путей к одним и тем же данным (жесткие ссылки, включая исходный файл) к файлу. Ячейка:

-rw-r--r--@ 2 [username] [group] [timestamp] HardLink
-rw-r--r--@ 2 [username] [group] [timestamp] Original
               ^ Number of hard links to the data
14
14
14
2013-08-15 08:52:16 +0000

Как насчет следующего проще? (Latter может заменить длинные сценарии выше!)

Если у вас есть конкретный файл <THEFILENAME> и вы хотите знать все его жесткие ссылки, разбросанные по каталогу <TARGETDIR> (которым может быть даже вся файловая система, обозначаемая /)

find <TARGETDIR> -type f -samefile <THEFILENAME>

Расширение логики, если вы хотите знать все файлы в <SOURCEDIR>, имеющие несколько жестких ссылок, разбросанных по каталогу <TARGETDIR>:

find <SOURCEDIR> -type f -links +1 \
  -printf "\n\n %n HardLinks of file : %H/%f \n" \
  -exec find <TARGETDIR> -type f -samefile {} \;
6
6
6
2015-04-21 19:32:47 +0000

Есть много ответов со скриптами, чтобы найти все жесткие ссылки в файловой системе. Большинство из них делают глупые вещи, такие как запуск find для сканирования всей файловой системы на -samefile для EACH-файлов с многосшифрованными ссылками. Это безумие; все, что вам нужно, это сортировать по номеру и распечатывать дубликаты. 0x2 и 0x2 и С одним проходом по файловой системе, чтобы найти и сгруппировать все наборы жестко связанных файлов 0x2 и 0x2 и 0x1 и 0x2 и 0x2 и Это гораздо быстрее, чем другие ответы для поиска нескольких наборов жестко связанных файлов.
find /foo -samefile /bar отлично подходит только для одного файла.

  • -xdev : ограничение для одной файловой системы. Необязательно, поскольку мы также печатаем FS-id в uniq в каталогах
  • ! -type d: записи . и .. означают, что они всегда связаны друг с другом.
  • -links +1 : счетчик ссылок строго > 1
  • -printf ... печатает FS-id, номер кода и путь. (С подкладкой на фиксированную ширину столбцов, о которой мы можем сказать uniq.)
  • sort -n | uniq ... числовая сортировка и унификация на первых 42 столбцах, разделение групп пустой строкой

Использование ! -type d -links +1 означает, что входные данные сортировки только столь же велики, как и конечный вывод uniq, поэтому мы не выполняем огромную сортировку строк. Если только вы не запустите его в подкаталоге, который содержит только один из набора жестких ссылок. В любом случае, при этом будет использовано намного меньше процессорного времени на обход файловой системы, чем при любом другом размещенном решении. Вывод

сэмплов:

find dirs -xdev \! -type d -links +1 -printf '%20D %20i %p\n' |
    sort -n | uniq -w 42 --all-repeated=separate

TODO?: un-pad вывод с awk или cut. uniq имеет очень ограниченную поддержку выбора поля, поэтому я забиваю выходной сигнал и использую фиксированную ширину. 20chars достаточно широки для максимально возможного числа входов или устройств (2^64-1 = 18446744073709551615). XFS выбирает номера кодов в зависимости от того, где на диске они распределены, а не от 0, так что большие файловые системы XFS могут иметь >32-битные номера кодов, даже если у них нет миллиардов файлов. Другие файловые системы могут иметь 20-значные номера, даже если они не гигантские.

TODO: сортируйте группы дубликатов по пути. Если они отсортированы по точке монтирования, то номер inode смешивает вещи вместе, если у вас есть пара разных подкаталогов, которые имеют много жестких ссылок. (т.е. группы дубликатов идут вместе, но на выходе они смешиваются). Окончательные

Окончательные sort -k 3 сортируют строки отдельно, а не группы строк как одну запись. Препроцессирование с помощью чего-нибудь, чтобы превратить пару новых строк в NUL-байт, и применение GNU sort --zero-terminated -k 3 могло бы выполнить эту хитрость. tr работает только с одиночными символами, а не с шаблонами 2->1 или 1->2. perl мог бы это сделать (или просто разобрать и отсортировать в perl или awk). sed может также работать.

3
3
3
2012-06-13 07:40:43 +0000

Это в некотором роде комментарий к собственному ответу и скрипту Torocoro-Macho, но он явно не поместится в поле для комментариев.


Переписать скрипт с более простыми способами поиска информации, и, таким образом, намного меньше ссылок на процесс.

#!/bin/sh
xPATH=$(readlink -f -- "${1}")
for xFILE in "${xPATH}"/*; do
    [-d "${xFILE}"] && continue
    [! -r "${xFILE}"] && printf '"%s" is not readable.\n' "${xFILE}" 1>&2 && continue
    nLINKS=$(stat -c%h "${xFILE}")
    if [${nLINKS} -gt 1]; then
        iNODE=$(stat -c%i "${xFILE}")
        xDEVICE=$(stat -c%m "${xFILE}")
        printf '\nItem: %s[%d] = %s\n' "${xDEVICE}" "${iNODE}" "${xFILE}";
        find "${xDEVICE}" -inum ${iNODE} -not -path "${xFILE}" -printf ' -> %p\n' 2>/dev/null
    fi
done

Я попытался сохранить его как можно больше похожим на ваш для легкого сравнения.

Комментарии к этому скрипту и вашему

  • Всегда следует избегать $IFS магии, если достаточно глобуса, так как он неоправданно запутан, и имена файлов на самом деле могут содержать новые строки (но на практике в основном первая причина).

  • Вы должны избегать ручного разбора ls и такого вывода как можно больше, так как рано или поздно это вас укусит. Например: в вашей первой строке awk вы ошибаетесь на всех именах файлов, содержащих пробелы.

  • printf в конце концов часто спасает от неприятностей, так как он настолько устойчив к синтаксису %s. Он также дает вам полный контроль над выводом, и, в отличие от echo, согласован в all системах.

  • stat может сэкономить вам много логики в этом случае.

  • GNU find является мощным.

  • Ваши вызовы head и tail могли быть обработаны непосредственно в awk с помощью, например, команды exit и/или выбора в переменной NR. Это позволило бы сэкономить вызовы процесса, что почти всегда значительно улучшает производительность в трудных скриптах.

  • Ваши egrep с тем же успехом могли бы быть только grep.

2
2
2
2011-11-16 22:46:38 +0000

Основываясь на сценарии findhardlinks (переименованном в hard-links), это то, что я рефакторировал и заставил его работать.

Вывод:

# ./hard-links /root

Item: /[10145] = /root/.profile
    -> /proc/907/sched
    -> /<some-where>/.profile

Item: /[10144] = /root/.tested
    -> /proc/907/limits
    -> /<some-where else>/.bashrc
    -> /root/.testlnk

Item: /[10144] = /root/.testlnk
    -> /proc/907/limits
    -> /<another-place else>/.bashrc
    -> /root/.tested

 

# cat ./hard-links
#!/bin/bash
oIFS="${IFS}"; IFS=$'\n';
xPATH="${1}";
xFILES="`ls -al ${xPATH}|egrep "^-"|awk '{print $9}'`";
for xFILE in ${xFILES[@]}; do
  xITEM="${xPATH}/${xFILE}";
  if [[! -r "${xITEM}"]] ; then
    echo "Path: '${xITEM}' is not accessible! ";
  else
    nLINKS=$(ls -ld "${xITEM}" | awk '{print $2}')
    if [${nLINKS} -gt 1]; then
      iNODE=$(ls -id "${xITEM}" | awk '{print $1}' | head -1l)
      xDEVICE=$(df "${xITEM}" | tail -1l | awk '{print $6}')
      echo -e "\nItem: ${xDEVICE}[$iNODE] = ${xITEM}";
      find ${xDEVICE} -inum ${iNODE} 2>/dev/null|egrep -v "${xITEM}"|sed 's/^/ -> /';
    fi
  fi
done
IFS="${oIFS}"; echo "";
1
1
1
2015-01-20 18:00:05 +0000

Решение с графическим интерфейсом очень близко к вашему вопросу:

Вы не можете перечислить фактические жестко связанные файлы из “ls”, потому что, как указывали предыдущие комментаторы, “имена” файлов - это просто псевдонимы к одним и тем же данным. Однако, на самом деле есть инструмент с графическим интерфейсом, который очень близок к тому, что вы хотите, и который показывает список путей с именами файлов, которые указывают на те же самые данные (как жесткие ссылки) под linux, он называется FSLint. Опция, которую вы хотите, находится под “Name clashes” -> снимите флажок “check box $PATH” в Search (XX) -> и выберите “Aliases” (Псевдонимы) из выпадающего списка после “for…” (для…) в направлении верхнего среднего уровня.

FSLint очень плохо документирован, но я обнаружил, что, убедившись в том, что ограниченное дерево каталогов под “Search path” с флажком “Recurse?” и вышеупомянутыми опциями, после поиска программы формируется список жестко привязанных данных с путями и именами, которые “указывают” на те же данные.

1
1
1
2017-12-06 17:34:25 +0000

Вы можете настроить ls на подсветку жестких ссылок с помощью ‘псевдонима’, но, как уже говорилось, невозможно показать ‘источник’ жесткой связи, поэтому я добавляю .hardlink, чтобы помочь с этим.

Добавьте следующее где-нибудь в ваши .bashrc

alias ll='LC_COLLATE=C LS_COLORS="$LS_COLORS:mh=1;37" ls -lA --si --group-directories-first'

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

6
10
10
5
9