0

I am writing a script where the user is asked to enter a the file name that they want to change permissions, I am stuck with if there is more then one file that comes up in the search and If the user wants to use multiple files how would I go about that.

I have set up the find command and set it that it will be stored in a path.

read -r QUESTION
if [ "$QUESTION" = 1 ];
then
    echo "What is the name of the file you want to make read only?"
    read -r FILENAME
    find ~/ -name "$FILENAME"
    PATH=$(find ~/ -name "$FILENAME")
    echo
    pwd
    /bin/chmod -v 400 "$PATH"
    fi
fi

echo

The expected output would be that a user will be able to enter multiple files to which they will be able to change the permissions for all those files in one go. If they only want to change 1 file and multiple files show up in the find they can choose their 1 file.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
Toscy
  • 3
  • 1
  • [BashFAQ #20](https://mywiki.wooledge.org/BashFAQ/020) covers ways to either operate directly on the files `find` matches, or put them in an array (not a plain variable!) so you can operate on them separately. You can also loop directly over the names, as in [this answer](https://stackoverflow.com/questions/2171966/bash-rename-extension-recursive/10327048#10327048). – Gordon Davisson May 01 '19 at 17:54
  • Sorry I still have some questions, what would it be called when its PATH=$()? second thing is from the array lets say im using chmod, I can just call the array at the end of chmod to change all the files at once? – Toscy May 01 '19 at 21:21

1 Answers1

0

Don't overwrite $PATH unless you know what you're doing. This variable is used to find executables.

$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Like Gordon said; you have to put the output of find into an array instead of a variable. Note the quotes, otherwise files with spaces will cause errors.

ARRAY=("$(find . -name "my file.txt")")
for file in "${ARRAY[@]}"; do echo $file; done

I've taken the liberty to write the script in such a way that I think you're able change it to your needs. The script kind of explains itself, but feel free to ask questions. You should do some error checking yourself ;-)

#! /bin/bash

IFS=$'\n'

FOUND=()
echo "Enter a blank filename to stop input"
while read -p "Enter a file name: " file; do
        [ ! -z "${file}" ] || break
        file_found=$(find ${HOME} -name ${file})
        if [ -z "${file_found}" ]; then
            echo "File '$file' not found"
            continue
        fi
        FOUND+=(${file_found})
done

if [ ${#FOUND[@]} -gt 1 ]; then

        echo "Multiple files found, make a choice."
        for ((index=0; index<${#FOUND[@]};index++)); do
                echo "  -> $index = ${FOUND[$index]}"
        done
        echo "  -> 0 1 .. n = Item 0, 1, .., n"
        echo "  -> * = Everything"
        echo "  -> Leave empty to abort"

        read -p "Choice(s): " CHOICE

        if [ -z "${CHOICE}" ]; then
                echo "Nothing chosen, aborting"
        elif [ "${CHOICE}" = "*" ]; then
                chmod -v 400 ${FOUND[@]}
        else
                FILES=()
                IFS=' '
                for choice in ${CHOICE}; do
                        FILES+=("${FOUND[$choice]}")
                done
                chmod -v 400 "${FILES[@]}"
        fi
elif [ ${#FOUND[@]} -eq 1 ]; then
        chmod -v 400 $FOUND
else
        echo "Not found"
        exit 1
fi

exit 0

Note: I didn't thought of this before, but it's possible to supply a here-document instead of using the script interactively:

$ ./test.sh << EOF
file1.txt
file 2.txt

*
EOF
Bayou
  • 3,293
  • 1
  • 9
  • 22
  • If we want the user to choose the directory they want to search, or even we just default it that it searches starting at ~/, then we wouldn't use mydir? Would you just have the input be set in the same place as mydir? – Toscy May 01 '19 at 22:32
  • 1
    I don't recommend using `ARRAY=($(find ... ))`, because it'll be confused by filenames with spaces and/or wildcard characters. (I live mostly on macOS, where spaces are common in filenames.) I'd use one of the techniques in [BashFAQ #20](https://mywiki.wooledge.org/BashFAQ/020) instead. Also, use double-quotes around references, like `chmod -v 400 "${FILES[@]}"`. – Gordon Davisson May 01 '19 at 22:51
  • If I didn't want users to choose which directory they can search in, I would remove the MYDIR variable entirely and use $HOME in the find command. @GordonDavisson has a good point. I personally never use files with spaces in them, thus this script will break when you try to find such files. You have to use [IFS variable](https://unix.stackexchange.com/questions/184863/what-is-the-meaning-of-ifs-n-in-bash-scripting). I will update my answer. – Bayou May 02 '19 at 09:53
  • Thanks for the response, second question then in regards to using an Array, If the user wants to call multiple files of their choosing and in different directories and then have all those files placed into one command ex: chmod * * file1 file2 how would you go about that? That's where my original question stemmed. – Toscy May 02 '19 at 17:29
  • I would create a loop in that the array is continuously filled with files found from the user input. I will update the script. – Bayou May 02 '19 at 21:55