Linux: найти все символьные ссылки данного "исходного" файла? (обратный "readlink")
Рассмотрим следующий фрагмент командной строки:
$ cd /tmp/
$ mkdir dirA
$ mkdir dirB
$ echo "the contents of the 'original' file" > orig.file
$ ls -la orig.file
-rw-r--r-- 1 $USER $USER 36 2010-12-26 00:57 orig.file
# create symlinks in dirA and dirB that point to /tmp/orig.file:
$ ln -s $(pwd)/orig.file $(pwd)/dirA/
$ ln -s $(pwd)/orig.file $(pwd)/dirB/lorig.file
$ ls -la dirA/ dirB/
dirA/:
total 44
drwxr-xr-x 2 $USER $USER 4096 2010-12-26 00:57 .
drwxrwxrwt 20 root root 36864 2010-12-26 00:57 ..
lrwxrwxrwx 1 $USER $USER 14 2010-12-26 00:57 orig.file -> /tmp/orig.file
dirB/:
total 44
drwxr-xr-x 2 $USER $USER 4096 2010-12-26 00:58 .
drwxrwxrwt 20 root root 36864 2010-12-26 00:57 ..
lrwxrwxrwx 1 $USER $USER 14 2010-12-26 00:58 lorig.file -> /tmp/orig.file
На этом этапе я могу использовать readlink, чтобы увидеть, что такое "исходный" (ну, я думаю, что обычный термин здесь-либо "цель", либо "источник", но те, кто в моем уме, также могут быть противоположными понятиями, поэтому я просто назову его "оригинальным") файл символьных ссылок, т. е.
$ readlink -f dirA/orig.file
/tmp/orig.file
$ readlink -f dirB/lorig.file
/tmp/orig.file
... Тем не менее, я хотел бы знать, есть ли команда, которую я мог бы запустить в "исходном" файле, и найти все символические ссылки, которые указывают на него? Другими словами, что-то как (псевдо):
$ getsymlinks /tmp/orig.file
/tmp/dirA/orig.file
/tmp/dirB/lorig.file
Заранее спасибо за любые комментарии,
Ура!
6 ответов:
Я не видел команды для этого, и это не простая задача, так как целевой файл содержит нулевую информацию о том, какие исходные файлы указывают на него.
Это похоже на" жесткие " ссылки, но, по крайней мере, они всегда находятся в одной и той же файловой системе, поэтому вы можете сделатьfind -inode, чтобы перечислить их. Мягкие ссылки более проблематичны, так как они могут пересекать файловые системы.Я думаю, что вам нужно будет в основном выполнить
ls -alдля каждого файла во всей иерархии и использоватьgrepдля поиска-> /path/to/target/file.Например, вот один, который я запустил в своей системе (отформатированный для удобства чтения - эти последние две строки на самом деле находятся на одной строке в реальном выводе):
pax$ find / -exec ls -ald {} ';' 2>/dev/null | grep '\-> /usr/share/applications' lrwxrwxrwx 1 pax pax 23 2010-06-12 14:56 /home/pax/applications_usr_share -> /usr/share/applications
Используя GNU
find, это позволит найти файлы, которые жестко связаны или символически связаны с файлом:find -L /dir/to/start -samefile /tmp/orig.file
Символьные ссылки не отслеживают то, что указывает на данный пункт назначения, поэтому вы не можете сделать лучше, чем проверить каждую символьную ссылку, чтобы увидеть, указывает ли она на нужный пункт назначения, например
for i in *; do if [ -L "$i" ] && [ "$i" -ef /tmp/orig.file ]; then printf "Found: %s\n" "$i" fi done
Вот что я придумал. Я делаю это на OS X, которая не имеет
readlink -f, поэтому мне пришлось использовать вспомогательную функцию, чтобы заменить ее. Если у вас есть правильныйreadlink -f, Вы можете использовать его вместо этого. Кроме того, использованиеwhile ... done < <(find ...)не является строго необходимым в этом случае, простойfind ... | while ... doneбудет работать; но если вы когда-либо хотели сделать что-то вроде установки переменной внутри цикла (например, количество совпадающих файлов), версия канала потерпит неудачу, потому что циклwhileбудет выполняться в подрешетке. Наконец, обратите внимание, что я используюfind ... -type lтаким образом, цикл выполняется только на символьных ссылках, а не на других типах файлов.# Helper function 'cause my system doesn't have readlink -f readlink-f() { orig_dir="$(pwd)" f="$1" while [[ -L "$f" ]]; do cd "$(dirname "$f")" f="$(readlink "$(basename "$f")")" done cd "$(dirname "$f")" printf "%s\n" "$(pwd)/$(basename "$f")" cd "$orig_dir" } target_file="$(readlink-f "$target_file")" # make sure target is normalized while IFS= read -d '' linkfile; do if [[ "$(readlink-f "$linkfile")" == "$target_file" ]]; then printf "%s\n" "$linkfile" fi done < <(find "$search_dir" -type l -print0)
Вдохновленный комментарием Гордона Дэвиссона. Это похоже на другой ответ, но я получил желаемые результаты, используя exec. Мне нужно было что-то, что могло бы найти символические ссылки, не зная, где находится исходный файл.
find / -type l -exec ls -al {} \; | grep -i "all_or_part_of_original_name"
Это может быть слишком упрощенно для того, что вы хотите сделать, но я нахожу это полезным. он не отвечает на ваш вопрос буквально, так как это не "запуск на исходном файле", но он выполняет задачу. Но, гораздо больше доступа к HDD. И, это работает только для "мягких" связанных файлов, которые являются большинством связанных файлов пользователя.
Из корневого каталога хранения данных или каталогов данных пользователей, где бы ни находились
symlinked"файлы" вorig.file, выполните команду find:# find -type l -ls |grep -i 'orig.file'Или
# find /Starting/Search\ Path/ -type l -ls |grep -i '*orig*'Обычно я использую часть имени, например,
Примечание: Я никогда не получал опцию-samefile, чтобы работать на меня.'*orig*'Для начала, потому что мы знаем, что пользователи переименуют (префикс) файл с простым именем с более описательным, например " Jan report from London _ orig.файл.2015.01.21 " или что-то в этом роде.Чистый, простой, легко запоминающийся
Надеюсь, что это помогает кто-то. Лэндис.
Comments