Home > Enterprise >  Selecting values based on parameter in bash
Selecting values based on parameter in bash

Time:10-27

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
  •  Tags:  
  • bash
  • Related