0

So, i already know how to check for the existence of a specific file:

if [ -f ~/file1 ]; then echo "is there" ; else echo "not there" ; fi
if [ -f ~/file2 ]; then echo "is there" ; else echo "not there" ; fi

and also for two files existence:

[[ -f file1 && -f file2 ]] && echo "both" || echo "not"

What i don't know however, is how to know the existence of two different files, while also printing their respective names (if either of them exist, if both exist, or print an error if none of them exist...)

So that:

  • if file1 exist but file2 don't -> it will print file1 as existing, and vise versa.

  • If file1 and file2 exist -> both of their filename is printed.

  • If none exist -> their filename will be printed as non-existing.

2
  • 1
    Is there a pattern in the file names, or this is just an hypothetical example? – schrodigerscatcuriosity Feb 5 at 22:46
  • just a hypothetical example :) @schrodigerscatcuriosity – Nordine Lotfi Feb 5 at 22:47
3

I would do this in a loop:

for pathname in ~/file1 ~/file2; do
    if [ -e "$pathname" ]; then
        printf '"%s" exists\n' "$pathname"
    else
        printf '"%s" does not exist\n' "$pathname"
    fi
done

This basically does the single test for existence for each pathname mentioned in the loop header, and decides what to output based on the result of the test. The output mentions the pathname examined and the result of the test.

If the pathnames matches a simple pattern, then this could be used in the loop:

for pathname in ~/file[12]; do ...; done

The question could also be interpreted like: Print each existing pathname, but if none of the files exists, print all pathnames and a note saying they don't exist.

set -- ~/file1 ~/file2

found=false
for pathname do
    if [ -e "$pathname" ]; then
        printf '"%s" exists\n' "$pathname"
        found=true
    fi
done

if ! "$found"; then
    printf '"%s" does not exist\n' "$@"
fi

I'm using the list of positional parameters as a list here, holding the pathnames that we want to examine. I do this because we potentially want to loop over this list twice; once with our -e tests, and then again (implicitly) in the call to printf if no file was found to exist.

Using an array in bash instead (requries a bit more typing):

files=( ~/file1 ~/file2 )

found=false
for pathname in "${files[@]}"; do
    if [ -e "$pathname" ]; then
        printf '"%s" exists\n' "$pathname"
        found=true
    fi
done

if ! "$found"; then
    printf '"%s" does not exist\n' "${files[@]}"
fi

Note that files=( ~/file1 ~/file2 ) could also be written

files[0]=~/file1
files[1]=~/file2

Just a comment about the -f test vs. the -e test. The -e test tests for existence, while the -f test tests for existence and file type. If the pathname does not refer to a regular file (or a symbolic link to a regular file), then the -f test may be false while the -e test, at the same time, may be true. A "regular file" is a file that is not a directory, socket, named pipe or any of the other common Unix file types.

I opted for the -e test rather than the -f test in my answer since you were using the word "exists" repeatedly in the question, while not mentioning anything about file types.

3
  • any alternative but by putting the two different files in different variable? so that instead of putting each filename in the $pathname variable, there would be two different ones. eg: $pathname1, $pathname2... – Nordine Lotfi Feb 5 at 23:06
  • 1
    @NordineLotfi See added bit in the middle, especially that last bit of code that uses an array, which is what you may want to use. Using totally separate variables is almost never what you want to do. – Kusalananda Feb 5 at 23:09
  • Thanks a lot for the very detailed answer (as always)! And yeah, that's mostly because i was curious in trying to do different action depending on 1. both file found, 2. one of the specific file found, 3. none of them found. Using an array would work for this well enough :) – Nordine Lotfi Feb 5 at 23:12

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.