-3

My homework asked me to

  1. The users are storing way too many files in their home directory and you would like to notify the top 5 offenders. You might want to run this script again for more or less users so this selection will prompt for the number of users to identify, check how many files they have in their home directory and send a list of those users to the standard output.

This is what I have for the first parts so far; I just cannot figure out #5.

echo " Please enter file name: "
read workingfile 
while true
 do
  echo "1)  Check who is logged into the system and pull up contact information"
  echo "2)  Check who has left a system process running and stop it"
  echo "3)  Check if two users have the same userid, and prompt to change it"
  echo "4)  Get a list of all users on file and list information about them"
  echo "5)   List the top 5 users that have to many files in their home directory and list them"

  echo " "
  echo -n "Choice: "
  read choice
  case "$choice" in

1)
      user=$(who | cut -d' ' -f1 | sort | uniq)
     grep "$user" $workingfile | sed 's/\:/ /g' | sed 's/stu[0-9]*//g'
     break
        ;;

2)
    echo "Please enter a username: "
    read user
    echo $user
    ps -u $user
    echo "Would you like to end the proccess for $user ? (yes or no)"
    read choice2
        if [ $choice2 = "yes" ];
                echo "killall -u USERNAME.”             break 
        else 
            echo "We will not be stopping any background proccesses!"
            break 
        exit
        fi
    ;;

3)
    sed -i '0,/stu5/{s/stu5/stu6/}' myuser.txt 
    sed -i '0,/stu5/{s/stu5/stu4/}' myuser.txt 
        echo "Testing if a user has the same id"
        if [[ $(grep -o "stu[0-9]" $workingfile | uniq -d) != 0 ]]; then
            result=$(grep -o "stu[0-9]" $workingfile | uniq -d)
            echo " We will be replacing the first instance of $result please input what number you'd like to replace it with!: "
            read input
            echo "replacing id..."
            sed -i '0,/stu5/{s/stu5/stu4/}' $workingfile
            cat $workingfile
            break
        else
            echo " There is no result!"
            break
         exit
         fi
    ;;

4) echo "List of all users in file: "
        cat $workingfile | sed 's/\:/ /g' | sed 's/stu[0-9]*//g'
        break

    ;;

closed as too broad by Thomas Dickey, Michael Homer, Rui F Ribeiro, kemotep, Stephen Kitt May 14 at 16:41

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 3
    So, what have you got so far?    Please do not respond in comments; edit your question to make it clearer and more complete. – Scott May 12 at 2:11
  • too many files or large files? ie, one 1tb file is OK but 100 1kb files are not? – ivanivan May 12 at 3:40
  • Enable quotas. That way, the "offenders" would not be able to store more data, and would contact you (rather than the other way around). – Kusalananda May 12 at 7:52
3

First, you have to make an assumption that either getent passwd actually returns all of the valid users (it doesn't in some cases) or that all the user's home directories follow the form /home/username (also not a great assumption). Let's go with the second assumption. You could then try something like

cd /home
for user in *; do printf "%s\t%s\n" $(find $user -type f | wc -l) $user; done | sort -rn > /tmp/sort.$$
for user in $(head -5 /tmp/sort.$$ | cut -f2); do notify $user; done

You just made two more assumptions. If the user has files with carriage returns in the name, the count with be off. Also, I'm assuming that the notify command here is some kind of email and it also assumes that the user's email is the same as their username. Probably a good assumption but again not always true.

  • With GNU userland you could do find "${user}" -type f -print0 | tr -dc '\0' | wc -c to count the number of files without worrying about weird filenames (embeded newlines, etc.). It's a dirty hack, though. Also, don't forget to quote your variables. – nxnev May 12 at 7:10
  • @nxnev I have assumed here that (1) /home is not writable by anybody other than root so nefarious users cannot create crafted directories and that (2) each username is well formed with no oddball characteristics that would mess with shell expansion. While I have the utmost respect for Stéphane Chazelas, I don't believe that his post applies to my usage of the variables. – doneal24 May 12 at 15:19
  • The issue with unquoted expansions is that any character can be affected by word splitting, not only spaces, tabs and newlines. For instance, IFS=b; var=abc; echo ${var} would print a c instead of abc. It's not the most common thing to see, but it happens. And, as Stéphane himself said, "you don't quote your variable because otherwise you're introducing security vulnerabilities. You quote your variables because it is wrong not to". – nxnev May 13 at 12:41

Not the answer you're looking for? Browse other questions tagged or ask your own question.