Use this same technique to find out which files are missing from packages:


For example all of the packages that are mono. I want to see all of the files.

Here is all of the packages listed with dpkg -l:

Now the package name (which is what we need) is in the 2nd column, so lets grab it with awk.

Next… recall that if you dpkg -L packagename , it will list all of its installed files and folders.

Sidenote / Example:

So lets pipe all of those package names extracted from dpkg -l & awk into a loop. Instead of doing a for loop (which is slow and launches bash everytime). Lets pipe it into xargs (that way its faster, and feels like a single command – which we will be proud of when we are done). Each package name will be piped as %% into xargs and it will run that dpkg -L %% one time per line (once for each of those 9 mono entries).

There we go… except 1) its hard to tell which file belongs to which package -> solution add a header line before it starts listing the files. 2) it lists files and folders. we just want the files.

Lets add that header.

Now lets filter out the files. We can send the output of each dpkg -L into another xargs that tests to see if the file is a regular file (not directory, not link). We used %% so we have to use something new like @@ (be careful not to use ## or $$ those chars are used by the system for other things, so becareful and think ahead). So every entry (file or folder) will run thru this: [[ -f @@ ]] && ls -lisah @@  (replace @@ with a file name and you will see that it tests if @@ and if it is a file it will return true, so the part after && is run which will write on the screen the output of ls -lisah @@ , if its not a file the the part after && is not run and nothing is output for that entry and it continue to next entry to see if its a regular file or not)

NOTE: test -f FILE && echo "true" || echo "false" or [[ -f FILE ]] && echo "true" || echo "false"  will return true if its a regular file and not a device file (so it will return true for files, hard links, and symlinks )

This next one should handle files with spaces better, because we quote around the files. Note that we quote files with single quotes inside double quotes. And quote files with double quotes inside single quotes.

Now that is a double xargs to be proud of. Its like a double loop. We are done.

Another way to do this is with a loop (which might handle files with spaces better). Notice that I put the whole thing in a subshell so that we don’t create or interfere with environment by setting package variable and f variable (those are my loop variables, that change with each succession of the loop). Also I set IFS=$'\n'  so that the for loop doesnt consider spaces as seperators for next entry, instead it will consider new lines as seperators (files might have spaces in the name, so this is crucial for looping thru files – as we have to assume some files will have spaces).. Also since this is in a subshell I dont have to worry about setting IFS back to what it was originally (default IFS is this: IFS=$' \t\n' )

Multi line:

One line (when converting to one line, put ; at the end of each line, just dont put it after the “do”s in the for loops – on the same topic also dont put ; after while loops):

(IFS=$'\n'; for package in `dpkg -l | grep mono | awk '{print $2}'`; do echo "--- $package ----"; for f in `dpkg -L $package`; do [[ -f "$f" ]] && ls -lisah "$f"; done; done)

The end.

Leave a Reply

Your email address will not be published. Required fields are marked *