0

I have primary files array and secondary files array in shell script. Both these arrays will contain file numbers.

#!/bin/bash
pri=(958 955 675 703 936 933 930 927 908 905 902 899 709)
snd=(953 947 943 939 916 915 1023 889 1010 1054 977 970 966)

# directories where we need to compare
primary=/primaries
secondary=/secondaries

echo "primary files: ${pri[@]}"
echo "secondary files: ${snd[@]}"

# now compare files in primary array `pri[@]` with `/primaries` directory. All files in primary array should be present in `/primaries` directory.
# and compare secondary array `snd[@]` with `/secondaries` directory. All files in secondary array should be present in `/secondaries` directory.
# If any of the file is missing, log a message.

Now all the files in primary array pri[@] should be present in /primaries directories and all the files in secondary array snd[@] should be present in /secondaries directories. File name is like this in both the directories proc_1041_test.data. Here 1041 is the file number.

How can I compare primary array file number with files in primaries directories and similarly for secondaries as well?

Note: /primaries and /secondaries directories can have sub directories in them so I just need to look for files in those two parent directories only not in any of the sub directories.

2

For one of the arrays:

for num in "${pri[@]}"; do
    name="proc_${num}_test.data"
    if [ ! -f "$primary/$name" ]; then
        printf '"%s" not found in "%s"\n' "$name" "$primary" >&2
    fi
done

That is, loop over the numbers in the array, construct the expected filename and test whether the expected filename exists¹ in the directory. If it doesn't, write a diagnostic message to the standard error stream.

Doing both sets of files in one go:

set -- "$primary" "$secondary"

typeset -n array
for array in pri snd; do
    for num in "${array[@]}"; do
        name="proc_${num}_test.data"
        if [ ! -f "$1/$name" ]; then
            printf '"%s" not found in "%s"\n' "$name" "$1" >&2
        fi
    done
    shift
done

This introduces a name reference variable array. When accessing ${array[@]}, the variable whose name has been assigned to array (in the loop, first pri then snd) will be access instead.

The directory names $primary and $secondary are assigned to the positional parameters $1 and $2 before the loop using set, and within the loop we shift $2 into $1 when we are done with the original $1.


¹ and is a regular file (or symlink to accessible regular file), change to [ ! -e "$primary/$name" ] && [ ! -L "$primary/$name" ] to check that the file exists regardless of its type.

  • @StéphaneChazelas The test for -L will be true if a link of the name used exists. But that does not mean that the file that that link points to (the actual file that contains data) actually exists. Yes, there is something at the position, but not necessarily an actual file with content. – Isaac Apr 15 '18 at 10:26
  • @isaac, yes, but here [ -L "$primary/$name" ] returning true means the $primary/$name file of type symlink exists. That second [ is actually only run in the case where the first [ succeeds, that is where we can't tell whether the file the link is (eventually) resolving to exists. – Stéphane Chazelas Apr 15 '18 at 10:39
  • @StéphaneChazelas Yes, I know. But when the second test returns true, the whole test returns true, and that may be understood that the final file that the link points to is in place and is readable. The first test will fail if the final file is not present. That is what should be the intent of the whole test. Maybe (and only maybe), if the -f test fails, then raise a warning that there is a link of the same name and that it is broken because the final file does not exist. That is a completely different logic and test. – Isaac Apr 15 '18 at 10:46
  • @isaac, the OP didn't specify what type of files those were or may be, whether they were regular files, fifos, directories, devices... or symlinks. It's not uncommon to create flag files as symlinks whose target may not resolve to an actual path for instance. -f is for regular file only after symlink resolution, the ¹ note is for all other types of files. For readable, you'd need -r (which does not imply -f). – Stéphane Chazelas Apr 15 '18 at 10:51
  • @StéphaneChazelas You are missing the point. – Isaac Apr 15 '18 at 11:14

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.