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
  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

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

    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 
            echo "We will not be stopping any background proccesses!"

    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
            echo " There is no result!"

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

  • 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 '19 at 2:11
  • too many files or large files? ie, one 1tb file is OK but 100 1kb files are not? – ivanivan May 12 '19 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 '19 at 7:52

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 '19 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 '19 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 '19 at 12:41

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