I'm still pretty new to unix and scripting and I'm trying to write a script that can take an input directory from the user, check if it exists, then compare the number of files in the given directory to the current directory and report which has more files. My code mostly works, as long as I input a child directory. If I try and use the script and input a parent, or another child along a different branch, it cannot find the directory, even when given the full path. I know that similar questions were asked regarding the test command, but none (that I could find) addressed what to do when test can't recognize a directory that does, in fact, exist.

read -rp "Input the path..." dir2
    if [ ! -d "$dir2" ]; then
    echo "...does not exist"

...the remainder of the code works fine. This is where the troubles lie.

EDIT: The general idea is to find any directory from any other directory but that isn't happening. For example from my ~/public_html as pwd, if I run the script and input ~/schoolwork, or even the full path, it cannot recognize the directory.

I have also reversed the logic (so that my function checks if it exists, then performs the operations, else returns an error) as well as the method posted here. the results are the same.

  • " but none (that I could find) addressed what to do when test can't recognize a directory that does, in fact, exist." How can this be possible ? [ ! -d $dir ] is not working? Can you give a more complete example? And how you are inputing this parent directory? – Luciano Andress Martini Jul 28 '17 at 18:27
  • @LucianoAndressMartini -d dir works as long as i'm looking for a child. If i put a parent into $dir2, or a child along a different path, it won't find it. I've input the path two different ways, with pwd being ~/public_html, I input ~/schoolwork, as well as /home/students/UID/schoolwork, and in both cases it was unable to find the directory. It definitely exists though. My operations for comparing the file sizes works fine. It's just the test that's giving me trouble. – Turfer Jul 28 '17 at 18:32

The issue that you are having is with tilde expansion. If you input ~/schoolwork at the prompt of your script, the tilde at the start is just another character and won't be expanded to the path of your home directory when you test it with [ ! -d "$dir2" ]. Likewise, you would also not be able to input $HOME/schoolwork as the variable $HOME would never be expanded.

In general, it's a bad idea to prompt a user to input pathnames. Pathnames are much easier to type on the command line where both tildes and variables are expanded before the script or program is executed. Additionally, giving a pathname on the command line would allow the user to use tab-completion, which in turn would decrease the risk of misspellings.

So, you want your user to use your script like

./script.sh path/to/some/directory

For example,

./script.sh ~/schoolwork

Here, the shell would expand the path before calling your script and the script would get a path like /home/turfer/schoolwork as its first and only argument.

Ok, so how to write this script?

Here's a suggestion for the start of it:


userdir=$1  # the directory pathname passed on the command line

if [ ! -d "$userdir" ]; then
    printf 'Your directory, %s, does not exist\n' "$userdir" >&2
    exit 1

Now, we have to count the number of files both in the current directory and in $userdir. Let's assume that we really mean files of any type (including sockets, symbolic links, directories etc.).

shopt -s dotglob   # also match hidden names

herefiles=( ./* )
therefiles=( "$userdir"/* )

If you'd want to only count regular files, you would loop over the things matched by these two patterns and only consider things that pass the [ -f ... ] test (though this would still count symbolic links to regular files).

Now we have all the names of everything in the current directory and in the user-specified directory in two arrays. Now we just need to compare the lengths of these arrays and say which one is the longest.

if [ "${#herefiles[@]}" -gt "${#therefiles[@]}" ]; then
    printf 'There are more files here than in %s\n' "$userdir"
elif [ "${#herefiles[@]}" -lt "${#therefiles[@]}" ]; then
    printf 'There are more files in %s than in here\n' "$userdir"
    printf 'There are an equal number of files here as in %s\n' "$userdir"

Instead of storing the names of the files in two separate arrays, you could obviously also manually count the names in two loops.


You can make your shell script like this:---

read -rp "Input the path..." dir2
#First Check the existence of directory
if [[ -d "$dir2" ]]
    #If it is a valid directory then count the number of files in each directory
    count1=$(find $dir1 -type f | wc -l)
    count2=$(find $dir2 -type f | wc -l)
    #Compare the number of files in the two directories
    if [ $count1 -gt $count2 ]
         echo "Current Directory has more files"
    else if [ $count1 -eq $count2 ]
         echo "Both Directories have same number of files"
         echo "Input Directory has greater number of files"
    #If not a valid directory
    echo "Invalid Directory"
  • This would count recursively down into subdirectories, and would count wrong if any filename contained one or several embedded newlines. It would also fail on any directory that contained whitespaces due to variable expansions being unquoted and the $pwd variable is probably unset, so you would get an error from find. – Kusalananda Nov 13 '18 at 22:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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