Example: Opening an existing ISO
This example will show how to examine an existing ISO. Here’s the complete code for this example:
import sys
import pycdlib
iso = pycdlib.PyCdlib()
iso.open(sys.argv[1])
for child in iso.list_children(iso_path='/'):
print(child.file_identifier())
iso.close()
Let’s take a closer look at the code.
import sys
import pycdlib
As we’ve seen before, import pycdlib. We also import the sys module so we get access to the command-line arguments.
iso = pycdlib.PyCdlib()
iso.open(sys.argv[1])
As we saw in the last example, create a new PyCdlib object. Once we have the object, we can then open up the file passed on the command-line. During the open, PyCdlib will parse all of the metadata on the ISO, so if the file is coming over a network, this may take a bit of time. Note that besides the open method, there is also an open_fp method that takes an arbitrary file-like object.
for child in iso.list_children(iso_path='/'):
print(child.file_identifier())
Use the list_children API from PyCdlib to iterate over all of the files and directories at the root of the ISO. As discussed in the Creating a new, basic ISO example, the paths are Unix-like absolute paths.
Note that iso_path selects the plain ISO9660 view of the filesystem, so the names printed above will be the ISO9660 names. Those are restricted to upper-case letters, digits, and underscores, are truncated to 8.3 (or 31 characters, depending on the interchange level), and carry a trailing version number, so a file that shows up as install-tl-windows.bat on a desktop operating system may be listed here as INSTALL_.BAT;1. The full names live in one of the ISO extensions: Rock Ridge (mostly Linux/Unix ISOs), Joliet (mostly Windows ISOs), or UDF (DVDs and many modern ISOs). Most real-world ISOs carry at least one of these, and desktop operating systems prefer them over the ISO9660 names. To see the same names that a desktop would show, check which extensions the ISO has with has_rock_ridge, has_joliet, and has_udf, and then pass rr_path, joliet_path, or udf_path instead of iso_path:
if iso.has_udf():
kwargs = {'udf_path': '/'}
elif iso.has_rock_ridge():
kwargs = {'rr_path': '/'}
elif iso.has_joliet():
kwargs = {'joliet_path': '/'}
else:
kwargs = {'iso_path': '/'}
for child in iso.list_children(**kwargs):
if child.is_dot() or child.is_dotdot():
continue
print(iso.full_path_from_dirrecord(child, rockridge='rr_path' in kwargs))
The same iso_path/rr_path/joliet_path/udf_path choice applies to every API that takes a path, including get_record, walk, get_file_from_iso, and open_file_from_iso. Note that the path must be spelled in the namespace you select; a Joliet path uses the Joliet name (/install-tl-windows.bat), not the ISO9660 name (/INSTALL_.BAT;1). full_path_from_dirrecord is used above because it decodes the name in whichever encoding the selected namespace uses (Joliet names, for instance, are UCS-2), while file_identifier returns the raw on-disk bytes.
iso.close()
Close out the PyCdlib object, releasing all resources and invalidating the contents. After this call, the object can be reused to create a new ISO or open up an existing ISO.