I have two bash array containing a few strings with the names of some files and their directories, and I have a directory that contains those files. I want to create a condition that is true when the array of strings contains files from that directory, with the exception of two files.
Example:
I have a directory dir
with 5 files: file1, file2, file3, file1-suffix and file2-suffix.
And I have this array of strings:
files=("dir/file1" "dir/file2" "dir/file1-suffix" "anotherdir/file")
directories=$("dir" "anotherdir")
I want to create a condition that is true if the array contains any of the elements that do not have the "-suffix" suffix (in the above example file1, file2 and file3). In the real case the number of files is arbitrarily large, so I can't do an If statement for each file.
Since they all share the same directory, I could check that, but then the condition would be true for the -suffix files and I don't care about those.
Right now my condition looks like this
if ( [[ " ${directories[*]} " =~ " ${DIRECTORY} " ]] && ! [[ " ${files[*]} " =~ '-suffix' ]] )
However, in the case where my files
array contains both suffix and nonsuffix files, this condition is evaluated as false, and I want it to be true in that case.
So, to sum up, I would like to obtain the following behavior in an "elegant" way:
files=("dir/file1" "dir/file2")
The condition is true.
files=("dir/file1" "dir/file1-suffix")
The condition is true.
files=("dir/file1-suffix" "dir/file2-suffix")
The condition is false.
files=("anotherdir/file1" "anotherdir/file2")
The condition is false.
I've also considered moving all the suffix files to a different directory, but I would prefer to avoid that option if possible. The question is a little bit tricky so sorry if I didn't make myself clear. Thanks in advance.
CodePudding user response:
If I follow your logic correctly, you want to check whether the array is nonempty after removing any entries which are not in $DIRECTORY
and any entries which match -suffix
.
matched=()
for item in "${files[@]}"; do
case $item in
*-suffix) continue;;
"$DIRECTORY"/*) ;;
*) continue;;
esac
# If you reach here, the condition is true already
matched =("$item")
done
The loop collects the matching files in matched
; you could check after the loop if the intersection contains any elements, but if all you care about is whether there is at least one file in the set, you could break
out of the loop and return true as soon as you get past the esac
.
Notice how we take care to properly quote any array items. Your use of "${files[*]}"
would blindly consider a file named "otherdir or dir/file"
as being in dir
which obviously isn't true at all.
Using an array is completely unnecessary and slightly wasteful if you just want to check whether a directory contains matches. Just loop over the files in the directory directly then.
for file in "$DIRECTORY"/*; do
case $file in *-suffix) continue;; esac
echo true
break
done
With shopt -s extglob
, you could also simply check whether "$DIRECTORY"/!(*-suffix)
expands to one or more files:
shopt -s extglob # if it's not already enabled
shopt -s nullglob # expand to empty string if no match
for f in "$DIRECTORY"/!(*-suffix); do
echo true for "$f"
done
CodePudding user response:
if the array contains any of the elements that do not have the "-suffix" suffix
So do exactly that. Just write the loop, that iterates over one array, excluding the one with -suffix, then for each element of another array check if it "contains".
check_it() {
for f in "${files[@]}"; do
if [[ "$f" = *-suffix ]]; then continue; fi
for d in "${directories[@]}"; do
if [[ "$f" = "$d"/* ]]; then
return 0
fi
done
done
return 1
}
CodePudding user response:
If you just want to test if any element of indexed array files
has not the -suffix
suffix, you can simply:
$ files=("dir/file1" "dir/file2" "dir/file1-suffix" "anotherdir/file")
$ if [[ "${files[*]%%*-suffix}" =~ ^\ *$ ]]; then echo no; else echo yes; fi
yes
$ files=("dir/file1-suffix" "dir/file2-suffix")
$ if [[ "${files[*]%%*-suffix}" =~ ^\ *$ ]]; then echo no; else echo yes; fi
no
We just substitute any foo-suffix
element by the empty string and check if the result expanded as a single word contains only spaces.