-->
Page 72
Let's put together a format string that will display the package name, followed by the name of every file that package contains. We'll try it on the adduser package first since it contains only one file:
# rpm -q --queryformat `%{NAME}: %{FILENAMES}\n' adduser adduser: /usr/sbin/adduser #
Hey, not bad: Got it on the first try. Now let's try it on a package with more than one file:
# rpm -q --queryformat `%{NAME}: %{FILENAMES}\n' etcskel etcskel: (array) #
Hmmm. What went wrong? It worked before. Well, it worked before because the adduser package contained only one file. The FILENAMES tag points to an array of names, so when there is more than one file in a package, there's a problem.
But there is a solution. It's called an iterator. An iterator can step through each entry in an array, producing output as it goes. Iterators are created when square braces enclose one or more tags and literal text. Since we want to iterate through the FILENAMES array, let's enclose that tag in the iterator:
# rpm -q --queryformat `%{NAME}: [%{FILENAMES}]\n' etcskel etcskel: /etc/skel/etc/skel/.Xclients/etc/skel/.Xdefaults/etc/skel/.ba #
There was more output: It went right off the screen in one long line. The problem? We didn't include a newline escape sequence inside the iterator. Let's try it again:
# rpm -q --queryformat `%{NAME}: [%{FILENAMES}\n]' etcskel etcskel: /etc/skel /etc/skel/.Xclients /etc/skel/.Xdefaults /etc/skel/.bash logout /etc/skel/.bash profile /etc/skel/.bashrc /etc/skel/.xsession #
That's more like it. If we wanted, we could put another file-related tag inside the iterator. If we included the FILESIZES tag, we'd be able to see the name of each file, as well as how big it was:
# rpm -q --queryformat `%{NAME}: [%{FILENAMES} (%{FILESIZES} bytes) \n]'\ > etcskel etcskel: /etc/skel (1024 bytes) /etc/skel/.Xclients (551 bytes) /etc/skel/.Xdefaults (3785 bytes) /etc/skel/.bash logout (24 bytes) /etc/skel/.bash profile (220 bytes) /etc/skel/.bashrc (124 bytes) /etc/skel/.xsession (9 bytes) #
That's pretty nice. But it would be even nicer if the package name appeared on each line, along with the filename and size. Maybe if we put the NAME tag inside the iterator:
Page 73
# rpm -q --queryformat `[%{NAME}: %{FILENAMES} (%{FILESIZES} bytes) \n]'\ > etcskel etcskel: /etc/skel(parallel array size mismatch)#
The error message says it all. The FILENAMES and FILESIZES arrays are the same size. The NAME tag isn't even an array. Of course the sizes don't match!
5.2.2.11.7. Iterating Single-Entry TagsIf a tag has only one piece of data, it's possible to put it in an iterator and have its one piece of data displayed with every iteration. This is done by preceding the tag name with an equal sign. Let's try it on our current example:
# rpm -q --queryformat `[%{=NAME}: %{FILENAMES} (%{FILESIZES} bytes) \n]'\ > etcskel etcskel: /etc/skel (1024 bytes) etcskel: /etc/skel/.Xclients (551 bytes) etcskel: /etc/skel/.Xdefaults (3785 bytes) etcskel: /etc/skel/.bash logout (24 bytes) etcskel: /etc/skel/.bash profile (220 bytes) etcskel: /etc/skel/.bashrc (124 bytes) etcskel: /etc/skel/.xsession (9 bytes) #
That's about all there is to format strings. Now, if RPM's standard output doesn't give you what you want, you have no reason to complain. Just --queryformat it!
5.2.2.11.8. In Case You Were WonderingWhat's that? You say you don't know what tags are available? You can use RPM's --querytags option. When used as the only option (that is, rpm --querytags), it produces a list of available tags. It should be noted that RPM displays the complete tag name. For instance, RPMTAG_ARCH is the complete name, yet you'll only need to use ARCH in your format string. Here's a partial example of the --querytags option in action:
# rpm --querytags RPMTAG_NAME RPMTAG_VERSION RPMTAG_RELEASE ... RPMTAG_VERIFYSCRIPT #
Be forewarned: The full list is quite lengthy. At the time this book was written, there were more than 60 tags! You'll notice that each tag is printed in uppercase and is preceded with RPMTAG_. If we were to use that last tag, RPMTAG_VERIFYSCRIPT, in a format string, it could be specified in any of the following ways:
%{RPMTAG_VERIFYSCRIPT} %{RPMTAG_VerifyScript}
Page 74
%{RPMTAG_VeRiFyScRiPt} %{VERIFYSCRIPT} %{VerifyScript} %{VeRiFyScRiPt}
The only hard-and-fast rule regarding tags is that if you include the RPMTAG_ prefix, it must be all uppercase. The fourth example here shows the traditional way of specifying a tag: prefix omitted, all uppercase. The choice, however, is yours.
One other thing to keep in mind is that not every package will have every type of tagged information available. In cases where the requested information is not available, RPM will display (none) or (unknown). There are also a few tags that, for one reason or another, will not produce useful output when they are used in a format string. For a comprehensive list of queryformat tags, see Appendix D, "Available Tags for --queryformat."
Sometimes it's necessary to have even more information than we can get with -v. By adding another v, we can start to see more of RPM's inner workings:
# rpm -qvv rpm D: opening database in //var/lib/rpm/ D: querying record number 2341208 rpm-2.3-1 #
The lines starting with D: have been added by using -vv. We can see where the RPM database is located and what record number contains information on the rpm-2.3-1 package. Following that is the usual output.
In the vast majority of cases, it will not be necessary to use -vv. It is normally used by software engineers working on RPM itself, and the output can change without notice. However, it's a handy way to gain insight into RPM's inner workings.
Adding --root <path> to a query command forces RPM to assume that the directory specified by <path> is actually the root directory. In addition, RPM expects its database to reside in the directory specified by the dbpath rpmrc file entry, relative to <path>.
Normally, this option is only used during an initial system install or when a system has been booted off a rescue disk and some packages need to be re-installed in order to restore normal operation.