-2

When I do enter those commands individualy, I get the results I want:

cat /var/log/apt/history.log | grep 'apt install' > installation.txt
grep -v "nvidia" installation.txt > tmpfile && mv tmpfile installation.txt
awk -F"ll " '{print $2}' installation.txt > temp1
sed -n '/--/!p' temp1 > temp2
sed -n '/-f/!p' temp2 > installation.txt

But I do not find how to combine those ...

Here some the tests I made without the nvidia search to try to understand where it goes wrong first:

cat /var/log/apt/history.log | grep 'apt install' > file | awk -F"ll " '{print $2}' file > temp | sed -n '/--/!p' temp > file | sed -n '/-f/!p' file > installation.txt
cat /var/log/apt/history.log | grep 'apt install' > file | awk -F"ll " '{print $2}' file | awk -F"ll " '{print $2}' file | sed -n '/--/!p' file | sed -n '/-f/!p' file
cat /var/log/apt/history.log | grep 'apt install' > file | awk -F"ll " '{print $2}' file > temp | sed -n '/--/!p' temp > file | sed -n '/-f/!p' file > installation.txt

How can I combine these operations?

I want to be able to export the packages I've installed and include the function in script I made available on github.

I need to use this command in my packages.sh script.

  • There's almost certainly a better way to do what you want with a single awk command than combining those separate commands implemented in awk. If you post sample sample input and expected output we can help you. – Ed Morton Jan 27 '23 at 21:03
  • I'm happy you seem to have found a solution. I find it fascinating that you chose to use grep to remove lines matching nvidia, but then used sed to remove line containing -- or -f... I wonder if it was due to the initial dash? grep -v -e -- -e -f would have worked. An even better answer may have surfaced if you had described what the commands actually did (or what you hoped to achieve). – Kusalananda Jan 27 '23 at 21:06
  • 3
    What you have so far is an XY question, see https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem. – Ed Morton Jan 27 '23 at 21:10
  • As a general rule, if you want to combine grep, sed, and awk then you're almost always better off using just sed or awk - both can do everything grep can. cat isn't needed because all of those programs can read files without cat. In most cases, awk is a better choice than sed because awk can do everything sed can do and more. Another option is perl which can do everything awk can do and a lot more. In short: use awk or perl for anything more complex than a simple grep or s///. Learning them all is ideal but if you want to learn only one, learn perl. – cas Jan 28 '23 at 02:57
  • If a package is installed and laterl subsequently uninstalled, would you still want to list the package name? What about if it was uninstalled, and then re-installed as an automatic dependency? – Kusalananda Jan 28 '23 at 06:06
  • It is unclear whether you want to restrict the listed packages to a subset of all installed packages on the system, or if you want the list all installed packages on the system. Doing this for a list of known packages would be trivial, as you can ask the package-manager whether a package is installed or not. – Kusalananda Jan 28 '23 at 06:11

3 Answers3

2

The answers so far are fine and address what you're trying to do. My answer is directed more toward your understanding (or misunderstanding) of shell commands.

You have cat /var/log/apt/history.log | grep 'apt install' > file by which cat reads a file, passes it into a pipe which outputs into grep. You don't need cat, grep is quite capable of reading the file itself.

Second, there's that > file | awk business in the grep step. I'm not sure what that's supposed to do. > file means "direct the output to file (rather than dumping it out on the terminal)" But the | awk means "catch the output and send to awk". I don't think you can do both at the same time. (There is a tee command which sends copies of its input to two destinations but that's not what you're doing here)

Chris Davies
  • 116,213
  • 16
  • 160
  • 287
1

All combined into a single awk command as following:

awk -F'll ' '
  /apt install/ && !/nvidia|-[-f]/{ print $2 }
' /var/log/apt/history.log >installation.txt
αғsнιη
  • 41,407
1

An alternative approach to extract (and filter) the installed package name from the Commandline: entries of the apt history is to use a single sed command:

sed -e '/^Commandline: apt install /!d' -e 's///' \
    -e '/nvidia/d' -e '/--/d' -e '/-f/d' \
    </var/log/apt/history.log >installation.txt

The first line of two expressions first deletes all input lines that does not start with the string Commandline: apt install , and then deletes that string from the lines that do start with the string.

The second line contains a series of expressions that deletes lines containing any of the three strings nvidia, --, or -f.

The third line contains the input and output redirections.


Another possible way to list the manually installed packages on the system is to use

apt list --installed | sed -e '/automatic/d' -e 's,/.*,,'

... to list all installed packages while removing anything installed as an automatic dependency from the list (this clumsy command will also remove any package containing the string atuomatic in its name).

Kusalananda
  • 333,661
  • 1
    +1. apt list --installed 2>/dev/null | awk -F/ '! /^Listing\.\.\.|\[.*automatic.*\]/ {print $1}' works too. Excludes lines containing "automatic" inside square brackets and lines starting with "Listing...". stderr of apt is redirected to /dev/null because (my version of) apt whinges about apt not having a stable CLI interface. – cas Jan 28 '23 at 02:31
  • @Kusalananda This doesn't do the trick. I only want the lines I enter manualy, not all what the system's installing with it. –  Jan 28 '23 at 03:00
  • @Wingarmac It is not clear what "this" refers to. You mean the last command? Well, that clearly depends on how far back you log stretches, right? Your question does not make this clear, so I must assume that it contains all installation commands that were ever executed. This in turn means it may include commands that were later reverted (packages that were uninstalled), which means the last command in my answer would more correctly reflect the current state of the system. – Kusalananda Jan 28 '23 at 06:05