0

I want to make a small shell script that shows all the files in a file tree starting from a given directory that have the given user and size greater than a given size. Hence, my script will take as parameters the directory to start with, the username and the size. This is what I have so far:

#!/bin/bash

owner="valdsilviufarcas"
size=0

function display_owner_and_size()
{
    owner=`stat --format "%s" $1`
    size=`stat --format "%U" $1` 
}

function search()
{

    for elem in $1/*
    do
        display_owner_and_size "$elem"
        if [[ $owner == $2 && $size > $3 ]]
        then
            echo $elem
        fi
        if test -d "$elem"
        then
            search "$elem" $2 $3    
        fi
    done
}

search $1 $2 $3

However, I keep getting this error: Cannot stat: (bla-bla-bla) : No such file or directory. Why is the stat function not working?

0

2 Answers 2

0

You should simply use the find command:

find ${dir} -user ${user} -type f -size +${size}c -printf "%u\t%s\t%h/%f\n"

Replace the Bash variables ${dir} with the directory to examine recursively, ${user} with the user name or UID that should be displayed only and ${size} with the minimum file size in bytes (not inclusive! if you use the value 100, the smallest file that gets displayed can have 101 bytes).

This command will only print regular files, it ignores directories and special files like symlinks or devices in the output.

2
  • Thanks, it works, but my goal was to use the two functions display_owner_and_size and search because that's how it was mentioned in my assignment requirements, but still, thanks. Mar 3, 2016 at 10:09
  • Well, see it as an easy alternative way. You did not say that the goal must be achieved using a script with those two functions. But we're not a homework service either...
    – Byte Commander
    Mar 3, 2016 at 10:16
0

There are two different issues.

The first one is you're not quoting your variables: this ultimately makes stat fail for that reason:

  1. search $1 $2 $3 should be search "$1" "$2" "$3";
  2. for elem in $1/* should be for elem in "$1"/*;
  3. owner=`stat --format "%s" $1` should be owner=`stat --format "%s" "$1"`;
  4. size=`stat --format "%U" $1` should be size=`stat --format "%U" "$1"`;
  5. search "$elem" $2 $3 should be search "$elem" "$2" "$3".

The second one is when an empty directory is reached during the recursion, the expansion of for element in $1/* fails and the two stat commands are called on /path/to/empty/directory/*, which doesn't exist:

% bash script.sh /home/user user 0
stat: cannot stat ‘/home/user/Documenti/Musica/*’: No such file or directory
stat: cannot stat ‘/home/user/Documenti/Musica/*’: No such file or directory
stat: cannot stat ‘/home/user/Documenti/My Games/*’: No such file or directory
stat: cannot stat ‘/home/user/Documenti/My Games/*’: No such file or directory
stat: cannot stat ‘/home/user/Documenti/Video/*’: No such file or directory
stat: cannot stat ‘/home/user/Documenti/Video/*’: No such file or directory
stat: cannot stat ‘/home/user/home/user/*’: No such file or directory
stat: cannot stat ‘/home/user/home/user/*’: No such file or directory
stat: cannot stat ‘/home/user/Modelli/*’: No such file or directory
stat: cannot stat ‘/home/user/Modelli/*’: No such file or directory
stat: cannot stat ‘/home/user/Musica/*’: No such file or directory
stat: cannot stat ‘/home/user/Musica/*’: No such file or directory
stat: cannot stat ‘/home/user/Pubblici/*’: No such file or directory
stat: cannot stat ‘/home/user/Pubblici/*’: No such file or directory
stat: cannot stat ‘/home/user/Video/*’: No such file or directory
stat: cannot stat ‘/home/user/Video/*’: No such file or directory
% 

One way to fix that would be checking whether the file / directory exists before calling display_owner_and_size, so that to skip the current iteration if we're attempting to stat / traverse a directory that doesn't exist (since the directory is empty there's no reason to stat its content nor to keep traversing that branch of the tree):

[ -e "$elem" ] && display_owner_and_size "$elem" || continue

Adding to that, other errors are:

  1. owner=`stat --format "%s" "$1"` should be owner=`stat --format "%U" "$1"` and size=`stat --format "%U" "$1"` should be size=`stat --format "%s" "$1"`;
  2. You can't use > to make numerical comparisons. Use -gt: if [[ $owner == $2 && $size -gt $3 ]].

So the corrected script would be:

#!/bin/bash

owner="valdsilviufarcas"
size=0

function display_owner_and_size()
{
    owner=`stat --format "%U" "$1"`
    size=`stat --format "%s" "$1"`
}

function search()
{

    for elem in "$1"/*
    do
        [ -e "$elem" ] && display_owner_and_size "$elem" || continue
        if [[ $owner == $2 && $size -gt $3 ]]
        then
            echo $elem
        fi
        if test -d "$elem"
        then
            search "$elem" "$2" "$3"    
        fi
    done
}

search "$1" "$2" "$3"
5
  • Thanks for the answer, but it seems not to work. The console does not display anything after I enter the command Mar 3, 2016 at 10:06
  • @vladsilviuFarcas That's because size is 0, and 0 will never be greater than $3, unless you're passing a negative value. You want to invert the test (if [[ $owner == $2 && $3 > $size ]]) and calling the script passing a value greater than 0 (e.g. ./script.sh /home/user user 1).
    – kos
    Mar 3, 2016 at 10:09
  • Nope, still doesn't work with [[ $owner == $2 && $3 > $size ]] Mar 3, 2016 at 10:11
  • @vladsilviuFarcas Sorry, I mixed things up. Let me look into that.
    – kos
    Mar 3, 2016 at 10:13
  • @vladsilviuFarcas Fixed. Tested on my system, it should work correctly.
    – kos
    Mar 3, 2016 at 10:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .