user2836537
user2836537

Reputation: 31

Checking if multiple files exist — Unix script using arguments

I'm trying to write a UNIX shell script that will take a few file names as arguments and then search in the current directory for these files.

So I would type

$ script file1 file2 file3...

If the file name(s) exist it would exit with a 1; however if the file(s) do not exist it will end with a status 0.

Here is what I have so far:

#!/bin/bash
FILE=$1

if [ -f $FILE ];
then
echo "File $FILE exists."
else
echo "File $FILE does not exist."
fi

but it's for only one file at a time passed as an argument. I need multiple files at one time as arguments.

Upvotes: 3

Views: 16568

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 753605

The question is incomplete — do you want exit status 1:

  • if every one of the files is present,
  • if every one of the files is missing,
  • if at least one of the files is present,
  • if at least one of the files is missing,
  • or do you have some other N of M criterion in mind?

The fundamental technique for iterating over file name arguments is:

for file in "$@"
do
    ...body of loop...using "$file" when referring to the file
done

See also How to iterate over the arguments in a bash script.


If you want exit status 1 when every one of the files is present, you can exit with status 0 when you detect that a file is missing:

for file in "$@"
do
    if [ ! -e "$file" ]
    then echo "$file is missing" >&2; exit 0
    fi
done
exit 1

If you want exit status 1 when every one of the files is missing, you can exit with status 0 when you detect that a file is present:

for file in "$@"
do
    if [ -e "$file" ]
    then echo "$file is present" >&2; exit 0
    fi
done
exit 1

If you want exit status 1 when at least one of the files is present, you can exit with status 1 when you detect that a file is present:

for file in "$@"
do
    if [ -e "$file" ]
    then echo "$file is present" >&2; exit 1
    fi
done
exit 0

If you want exit status 1 when at least one of the files is missing, you can exit with status 1 when you detect that a file is missing:

for file in "$@"
do
    if [ ! -e "$file" ]
    then echo "$file is missing" >&2; exit 1
    fi
done
exit 0

If you have some other criterion in mind, you need to explain what it is, and how it would be applied for the cases 0, 1, 2, ... M files are specified on the command line.

If you want to see a report on each file, you need to use a slightly different structure. For the last case, where you want exit status 1 if at least one of the files is missing, you set the variable status to 0 before the loop, and in the body of the loop, set it to 1 if the condition is met, finally exiting with the current value of status.

status=0
for file in "$@"
do
    if [ ! -e "$file" ]
    then echo "$file is missing" >&2; status=1
    fi
done
exit $status

The changes for the other cases are similar; set the initial status to the default value, and override the default when you detect the contrary condition.

I used -e to test whether the name exists; you can use other more specific tests if the name must be a plain file, or a directory, or a block or character special device, or a symlink, or a FIFO or a socket or …

I used the >&2 notation so that the reports are sent to standard error rather than standard output. You might prefer to prefix the messages with $0, the name of the script. You might prefer that the messages are reported on standard output.

Upvotes: 5

Related Questions