3

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.

8
  • Do you exit with 1 even if a single file exists? And you exit with 0 if none of the files exist? Commented Nov 18, 2013 at 5:19
  • help test is your friend. Commented Nov 18, 2013 at 5:20
  • 1
    1. You haven't mentioned what you tried thus far. 2. Even your question isn't quite clear on what is the expected result, i.e. whether you want a certain exit code depending upon whether one of the files exist or all of those exist. Do you really think that this question should remain open? Commented Nov 18, 2013 at 5:24
  • 2
    Do you realize that 0 conventionally indicates success and 1 indicates failure? Do you want success 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? Commented Nov 18, 2013 at 5:26
  • 3
    @devnull - show some mercy! He's a new user and doesn't know how to ask questions. We can either shut him off or curate his question by asking questions. In time, he'll start asking quality questions. Commented Nov 18, 2013 at 5:30

1 Answer 1

5

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.