Как «найти» определенные символические ссылки в Linux?

Как «найти» определенные символические ссылки в Linux?

Мне бы хотелось найти findфайлы (со схожими функциями), но следовать и переходить только по определенным символическим ссылкам (путем сопоставления с шаблоном).

Очевидно, findчто сам по себе он не может с этим справиться: нет возможности настроить поведение следования по символическим ссылкам; и наивная find -Lлегкодоступная блокировка (или работающая крайне медленно).

решение1

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

ЗаСпецификация, findбудет обнаруживать бесконечные циклы, поэтому лайвлок не должен произойти. Ресурсы (включая время), которые тратятся впустую, могут быть проблемой, и я понимаю ваше беспокойство.

Прежде всего, используйте, -Lчтобы разрешить findследовать символическим ссылкам, по которым вы хотите, чтобы он следовал. Затем вам нужен способ обнаружения других символических ссылок.

In find -L -type lникогда не бывает истинным, но вы можете обнаружить символические ссылки с помощью -exec test -L {} \;(помните -exec … \;, это тоже тест, он успешен, если внутренняя команда завершается со статусом 0). Таким образом, вы все равно можете применить некоторые тесты специально к символическим ссылкам и -prune(или нет) соответственно.

Например, следующая команда будет спускать только те символические ссылки, имена которых начинаются fooили заканчиваются на bar:

find -L . -exec test -L {} \; ! \( -name 'foo*' -o -name '*bar' \) -prune -o -print

Какое бы выражение вы изначально ни хотели, поместите его после -prune -o. В приведенной выше команде «исходное» выражение — -print. Помните, -execчто подавляет неявное -print, поэтому, если вам нужно -print, добавьте его явно (как мы это сделали).

Обратите внимание, что -nameпроверяется имя самой симлинки. Если вы хотите проверить имя цели, то вам понадобится realpath, возможно basename, и некоторый код оболочки; например:

find -L . -exec test -L {} \; -exec sh -c '
   case "$(basename "$(realpath "$1")")" in
      baz* ) exit 0 ;;
      *qux ) exit 1 ;;
   esac
   exit 0
' find-sh {} \; -prune -o -print

Приведенная выше команда создаст -pruneлюбую символическую ссылку на любой файл, имя которого начинается с baz, но она создаст символические ссылки на каталоги с именами, заканчивающимися на qux(если они не начинаются с baz), и, наконец, -pruneвсе остальные символические ссылки.

Примечания:

  • realpathи basenameне являются переносимыми.
  • realpathразрешает все символические ссылки.
  • Поведение в случае неработающей символической ссылки может соответствовать вашим ожиданиям, а может и нет.
  • Вызов отдельного testдля каждого файла повредит производительности, но я не нашел лучшего способа. Вызов sh, realpathи basenameтакже плох в этом вопросе, но здесь это происходит только для символических ссылок, поэтому в большинстве случаев влияние будет ограниченным.
  • find-shобъясняется здесь:Какая вторая буква «ш» в слове sh -c 'some shell code' sh?
  • В примерах пути, которые получают -pruned, не будут -printed. Измените последний фрагмент на -prune -false -o -print, и они будут напечатаны. Смотритеобъяснение-false; на случай, если вам понадобится, есть портативная альтернатива .

Связанный контент