I am writing my first bash script and I can't find the solution to my problem.
Lets say I am calling ls -l
and I want to save the names of certain files to a variable.
Output of ls -l
:
-rw-r--r-- 1 user1 user1 125 Apr 19 2021 aaa
drwxrwxr-x 5 user2 user2 4096 Sep 7 15:54 bbbb
drwxr-xr-x 4 user3 user3 4096 Mär 16 2021 cccc
drwxr-xr-x 7 user1 user1 4096 Mai 18 15:32 asdf
To parse the output I use the following command:
`ls -l | while read a b c d e f g h j; do echo $c $j
Which results to:
user1 aaa
user2 bbbb
user3 cccc
user1 asdf
Now the step I cant figure it out is how to filter out based on on the values of j
. Lets say, we have an array values=(aaa cccc)
. How could I extend my command, so that it prints out the users only if the value of j
is a value in the array values
?
Final result should be:
user1 aaa
user3 cccc
CodePudding user response:
How could I extend my command, so that it prints out the users only if the value of j is a value in the array values ?
For each line, check if the second column is in the array. Check if a Bash array contains a value
containsElement () {
local e match="$1"
shift
for e; do [[ "$e" == "$match" ]] && return 0; done
return 1
}
result="user1 aaa
user2 bbbb
user3 cccc
user1 asdf"
values=(aaa cccc)
printf "%s\n" "$result" |
while IFS=' ' read -r user file; do
if containsElement "$file" "${values[@]}"; then
printf "%s %s\n" "$user" "$file"
fi
done
A more crude solution would be to:
... | grep -f <(printf ' %s$\n' "${values[@]}")
CodePudding user response:
It would probably be simpler if your array was an associative one (supported by recent versions of bash):
declare -A values=([aaa]=1 [cccc]=1)
ls -l | while read a b c d e f g h j; do [ -v values[$j] ] && echo "$c $j"; done
If your bash version supports associative arrays but not yet the [ -v var ]
test, you can replace it by [ -n "${values[$j] ok}" ]
.
But as explained in comments parsing the ls
output is strongly discouraged. In your case any file name with spaces or tabs, or even worse, newline characters, would break all this.
CodePudding user response:
If what you want is the owner of each file, use stat
. (If a single call to stat
per file is too big a bottleneck compared to one call to ls
, then you shouldn't be using bash
in the first place: use a language which provides direct access to the underlying system calls to retrieve the owner.)
for v in "${values[@]}"; do
user=$(stat ... "$v") # See man stat for the correct invocation
echo "$user $v"
done