¿Cómo almaceno los resultados de búsqueda en una variable para poder mostrarlos antes de modificarlos?

¿Cómo almaceno los resultados de búsqueda en una variable para poder mostrarlos antes de modificarlos?

Tengo este script que busca archivos con permisos incorrectos. Si se encuentra alguno, le pregunta al usuario si desea arreglarlo o mostrarlo. Los resultados de la búsqueda se almacenan en una variable para evitar ejecutar el mismo comando varias veces:

#!/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

El problema chmodarroja un error debido a las nuevas líneas:

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

Si elimino las comillas "$results", funciona un poco mejor, pero, por supuesto, los nombres de archivos que contienen espacios son problemáticos.

He estado jugando IFS=$'\n'pero no estoy seguro de dónde debería configurarlo. Esto no parece funcionar:

IFS=$'\n' chmod 644 $results

Sin embargo, esto hace:

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

Supongo que me pregunto si esto es correcto o si hay una manera mejor.

Respuesta1

Configurar IFSsolo las nuevas líneas ayuda, pero aún deja los problemas de 1) nombres de archivos con nuevas líneas (obviamente) y 2) nombres de archivos con caracteres globales. Por ejemplo, un archivo llamado *se expandiría a todos los nombres de archivo del directorio.

En Bash, use mapfile/ readarraypara completar una matriz en su lugar:

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

Ver también:

Respuesta2

En lugar de configurarlo IFSantes chmody desarmarlo inmediatamente después, parece funcionar igual de bien si lo configuro/desconfiguro antes/después.find yenvuelva el subshell en una matriz como se sugiere en los comentarios:

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

De esta manera, la matriz tiene la cantidad correcta de elementos y chmod 644 "${results[@]}"funciona como se esperaba, siempre y cuando no haya nombres de archivos que contengan caracteres de nueva línea (aunque no puedo imaginar por qué alguien haría tal cosa a propósito).

información relacionada