Как в find -exec заменить текущий файл на {}?

Как в find -exec заменить текущий файл на {}?

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

find . -exec if [[ ! -O {} ]]; then echo {}; fi ;

Но если я поставлю всю команду -execв кавычки, например так:

find . -exec 'if [[ ! -O {} ]]; then echo {}; fi' \;

Ни то, ни другое не работает, поскольку ссылка на текущий файл {}заключена в кавычки и поэтому не расширяется до файла.

Проблема в том, что я не знаю, как встроить {}текущий файл в более сложный, -execчем простой, например find . -exec grep smf {} \;(который использует {}только один раз). Как использовать -execопцию в find в командах, где вы ссылаетесь на текущий файл более одного раза? (Это использует {}больше времени).

решение1

Ваш код не работает, поскольку утилита, которую вы просите findзапустить, ifне существует (это ключевое слово в синтаксисе оболочки).

Тест -Oистинен, если аргумент — файл, принадлежащий текущему пользователю. Тот же тест можно выполнить сам по findсебе с помощью -user "$USER"(предполагая, что $USERрасширяется до текущего пользователя):

find . -type f ! -user "$USER"

Вы также можете использовать test -O, если ваша внешняя testутилита поддерживает этот нестандартный тест (проверьте man test):

find . -type f ! -exec test -O {} \; -print

Если вы все еще хотите или нуждаетесь в использовании -Oтеста, встроенного в bashоболочку, то вам придется создать bashоболочку для выполнения теста:

find . -type f -exec bash -c '[[ ! -O "$1" ]]' bash {} \; -print

Это запускает один встроенный bash -cскрипт для каждого найденного файла, который запускает тест на его первом аргументе ( $1). Аргумент передается в командной строке скрипта find( bashстрока перед ним {}будет помещена $0внутрь скрипта и будет использоваться этой оболочкой для сообщений об ошибках). Если тест истинен (файл не принадлежит вам), -printвступает в силу и печатает путь к файлу.

Вы можете сделать это немного эффективнее с помощью

find . -type f -exec bash -c '
    for pathname do
        [[ ! -O "$pathname" ]] && printf "%s\n" "$pathname"
    done' bash {} +

Это более эффективно, поскольку в bash -cскрипт передаются пакеты найденных путей.

... но использование -user "$USER"было бы лучшим вариантом.

Смотрите также:

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