Как сохранить результаты поиска в переменной, чтобы можно было отобразить их перед изменением?

Как сохранить результаты поиска в переменной, чтобы можно было отобразить их перед изменением?

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

#!/usr/bin/env sh

results=$(find "$0" -type f -not -perm 644)

if [ -z "$results" ]; then
    echo 'No files with incorrect permissions found'
else
    while true; do
        read -p 'Fix files with incorrect permissions? (yes/no/show) ' ans
        case "$ans" in
            Y | y | yes)
                echo 'Changing file permissions...'
                chmod 644 "$results"
                break;;
            N | n | no)
                break;;
            S | s | show)
                echo "$results";;
            *)
                echo 'Please answer yes or no';;
        esac
    done
fi

Проблема в том, что chmodвозникает ошибка из-за новых строк:

chmod: cannot access 'test/foo'$'\n''test/bar'$'\n''test/foo bar': No such file or directory

Если убрать кавычки "$results", то все будет работать немного лучше, но тогда, конечно, имена файлов, содержащие пробелы, станут проблематичными.

Я повозился с этим IFS=$'\n', но не уверен, где это установить. Похоже, это не работает:

IFS=$'\n' chmod 644 $results

Однако это:

IFS=$'\n'
chmod 644 $results
unset IFS

Думаю, мне просто интересно, правильно ли это или есть способ лучше.

решение1

Настройка IFSтолько на новые строки помогает, но все еще оставляет проблемы 1) имен файлов с новыми строками (очевидно), и 2) имен файлов с символами glob. Например, файл с именем *будет расширяться до всех имен файлов в каталоге.

В Bash вместо этого используйте mapfile/ readarrayдля заполнения массива:

mapfile -d '' files < <(find . -type f ! -perm 0644 -print0)
printf "%d matching files found\n" "${#files[@]}"
printf "they are:\n"
printf "  %q\n" "${files[@]}"

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

решение2

Вместо того, чтобы устанавливать его IFSдо chmodи снимать его сразу после, похоже, что он работает одинаково хорошо, если я устанавливаю/снимаю его до/послеfind иоберните подоболочку в массив, как предложено в комментариях:

IFS=$'\n'
results=($(find "$0" -type f -not -perm 644))
unset IFS

Таким образом, массив будет содержать правильное количество элементов и chmod 644 "${results[@]}"работать так, как и ожидалось, при условии, что в именах файлов не будет символов новой строки (хотя я не могу себе представить, зачем кому-то это делать намеренно).

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