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.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user2836537
  • 31
  • 1
  • 1
  • 3
  • Do you exit with 1 even if a single file exists? And you exit with 0 if none of the files exist? – Chandranshu Nov 18 '13 at 05:19
  • `help test` is your friend. – devnull Nov 18 '13 at 05:20
  • just exit with 1 for exist and 0 if none – user2836537 Nov 18 '13 at 05:21
  • 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?_ – devnull Nov 18 '13 at 05: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? – Jonathan Leffler Nov 18 '13 at 05:26
  • see what i tried above thanks – user2836537 Nov 18 '13 at 05:28
  • 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. – Chandranshu Nov 18 '13 at 05:30
  • Read [How to iterate over arguments in `bash` script](http://stackoverflow.com/questions/255898/how-to-iterate-over-arguments-in-bash-script/256225#256225) to see how to process the arguments one at a time. Your one-file code does not answer the question of when you want success and when you want failure for the multi-file case. FYI, the semi-colon after the test is superfluous when the `then` is on the next line (the layout I prefer, though I'd indent the `echo` lines if it were my code). There are those who prefer the `then` on the same line as the test (e.g. company standard where I work). – Jonathan Leffler Nov 18 '13 at 05:30

1 Answers1

4

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.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278