I can run the following from the bash command line:
$ pkg="linux-headers-$(uname -r)"
$ dpkg -l "${pkg}" | grep '^ii '
ii linux-headers-5.15.0-130-generic 5.15.0-130.140~20.04.1 amd64 Linux kernel headers for version 5.15.0 on 64 bit x86 SMP
However, when I create a file with the package name in it and run the same command reading the file input, it fails. Create the file ...
$ echo "build-essential" > pkgs.list
$ echo "linux-headers-\$(uname -r)" >> pkgs.list
$ echo "gcc" >> pkgs.list
$ cat pkgs.list
build-essential
linux-headers-$(uname -r)
gcc
... and read it as input:
$ IFS=$'\n' ; while read pkgline ; do dpkg -l "${pkgline}" | grep '^ii ' ; done < pkgs.list
ii build-essential 12.8ubuntu1.1 amd64 Informational list of build-essential packages
dpkg-query: no packages found matching linux-headers-$(uname -r)
ii gcc 4:9.3.0-1ubuntu2 amd64 GNU C compiler
What needs to change to make the dpkg -l command work inside the loop, reading from a file, the way it did on the command line? I have full control over the file contents and the while loop, but I prefer not to substitute the value of $(uname -r) in the file. The text should remain "$(uname -r)" (or some variation of that) in the file. I have tried several ways to use "eval" without success, including the answer to bash : read a line from a file and interpret this line. Perhaps I'm being dense, but if that's the answer I don't see how to apply it to this case.
Edit: Hmm, yes, I was dense. The ways I tried to use "eval" were:
dpkg -l eval ${pkgline}
dpkg -l ${!pkgline}
p=eval "${pkgline} ; dpkg -l "${p}"
and even
dpkg -l "eval echo -e ${pkgline}"
after reading bash : read a line from a file and interpret this line. But what works is the straightforward:
eval dpkg -l "${pkgline}"
Well, thank you for asking.
Using echo
instead of dpkg
which I don't have on my machine:
$ while IFS= read -r pkgline; do eval echo "$pkgline"; done < pkgs.list
build-essential
linux-headers-3.5.4-1.x86_64
gcc
Just replace echo
with dpkg -l
.
The above is assuming you're in control of the contents of your input file and so can't be at risk of executing some malicious code via the eval
.