찾기 결과를 수정하기 전에 표시할 수 있도록 변수에 어떻게 저장합니까?

찾기 결과를 수정하기 전에 표시할 수 있도록 변수에 어떻게 저장합니까?

권한이 잘못된 파일을 찾는 스크립트가 있습니다. 발견된 항목이 있으면 이를 수정할 것인지 아니면 표시할 것인지 사용자에게 묻습니다. 동일한 명령을 여러 번 실행하는 것을 피하기 위해 찾기 결과는 변수에 저장됩니다.

#!/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[@]}"개행 문자가 포함된 파일 이름이 없는 한 예상대로 작동합니다(누군가 의도적으로 그런 일을 하는 이유는 상상할 수 없지만).

관련 정보