Linux Format

Add selecting and printing file dialogs

Karsten Günther reveals how to save file names and paths, select them with YAD and print with the printer dialog.

- OUR EXPERT Karsten Günther loves pretty things, so he loves making terminal tools a little prettier for use with YAD.

If parts of a command line are to be executed first in order to be able to use their output in the command line, then the constructi­on $(first) is used. BASH replaces this constructi­on with the standard output of the embedded command line.

Usually files processed by shell scripts are selected either by the user or with name patterns. The calling shell interprets the name patterns and takes over the file paths. YAD offers the ability to use a GUI way of specifying files in a dialog. However, when it comes to multiple file names as well as file names containing spaces, an extra level of complexity has to be dealt with. When selecting files manually, the shell usually masks such filenames automatica­lly when completing the selection, but the main problem remains: saving paths with spaces so that they can be used later.

No matter how a group of files is obtained, their names – or entire paths – must be stored for processing. As a structure for such data, BASH offers simply indexed arrays (there are also others). BASH creates an array whenever a variable assignment is created in the form ARRAY=( E l e m e n t e ) . The individual elements of the array are accessed in the form ${ARRAY[INDEX]} . The INDEX starts at zero and automatica­lly ends with the number of the last element contained in the array. ${ARRAY[*]} and ${ARRAY[@]}

output all elements of the array (the man page explains the difference). Using the constructi­on ${!ARRAY[*]}

the BASH generates a list of all indices available for the array. In the example from above, the result is therefore for i in ${!ARRAY[*]} do echo “{ARRAY[$i]}: ${ARRAY[$i]}”; done

{ARRAY[0]}: E

{ARRAY[1]}: l

{ARRAY[2]}: e

{ARRAY[3]}: m

{ARRAY[4]}: e

{ARRAY[5]}: n

{ARRAY[6]}: t

{ARRAY[7]}: e

Whether the display must always be as indicated in the echo line is a matter of taste. The whole procedure can be combined into the extremely useful function dump_array . The name of an array variable is passed as an argument. Error handling is omitted to keep the function simple; the internal variable __ARRAY is named with two underscore­s so that ARRAY can also be used as an argument of the function:

dump_array(){ declare -n __ARRAY="$1”; for i in ${!__ARRAY[*]} do echo “\${$1[$i]}: ${__ARRAY[$i]}”; done

}

If elements such as file names in an array assignment contain spaces, these elements must be in single or double quotes: VAR=(sp a ce “sp a ce") creates four array entries. The double quotes combine the material between them into one entry.

$ dump_array VAR

{VAR[0]}: sp

{VAR[1]}: a

{VAR[2]}: ce

{VAR[3]}: sp a ce

Select with YAD

$(yad --file) calls the standard file selection dialog. Exactly one file can be selected with a double-click or the [OK] button (this also applies to directorie­s). When

exiting, the program writes the selected entry into the standard output channel. To save it, the code looks like this: FILENAME=$(yad --file) . In this case it’s irrelevant whether the file name contains spaces. If only the filename is required then basename extracts it, while dirname returns the rest of the path.

The situation changes abruptly if multiple selections with the option --multiple are possible: yad --file --multiple . When outputting via the standard output channel, the selections appear in this form: path1/ file1|path2/file2|... . As a separator between two selected paths, YAD thus uses the pipe symbol, which adjusts the option --separator=SEPARATOR . However, there must be a space or a line break ( \n ) (NewLine-Character) here so that BASH can sort the entries correctly into an array. Note that --separator=’ ‘ (a space) can be used as a separator, but this leads to exactly the same problems and the same solution.

FILES=($(yad --file --multiple --separator='\n'))

already does this correctly. But if the paths (possibly) contain spaces, then these entries must be in quotes to be recognised as belonging together. This is done with the YAD option --quoted-output , which affects all entries equally. The entire command line now looks like this: FILES=($(yad --file --multiple --quoted-output --separator='\n')) . This is completely correct, but surprising­ly still doesn’t give the correct result, but:

$ dump_array FILES

{FILES[0]}: ‘/tmp/sp

{FILES[1]}: a

{FILES[2]}: ce’

What exactly happens here isn’t so easy to see, but the solution is that the command line must first be completely constructe­d before the variable assignment takes place. In particular, the output of the embedded command line $(...) must already be available when the shell interprets this command line. The solution lies in the built-in shell command eval . It evaluates its argument, constructs the command line and then executes it. Now it works as expected, as dump_array shows:

$ eval FILES=($(yad --file --multiple --quoted-output --separator='\n'))

$ dump_array FILES

{FILES[0]}: /tmp/sp a ce

Another option makes things easier for users: YAD opens the current directory by default when the selection dialog is called. Often, however, you might want to open a different, preset directory, for example /tmp. To achieve this, the option --filename="PATH" is used, which has a different function in another context. Tilde expansions can also be used in the argument PATH .

Filter directory entries

If the directorie­s displayed in the file dialog contain a lot of entries, it’s useful to hide irrelevant entries. This is possible in several ways and is completely handled by the file dialog. Users only have to define what they want to see – they “filter” the entries. Three options control the basic procedures.

--file-filter=NAME|PATTERN1|PATTERN2... is a

general filter that’s based on file names.

--mime-filter='NAME | MIME1 | MIME2...‘ identifies

file types based on MIME types.

--image-filter=[NAME] is used to select images, controlled by the format of the images.

In the following examples, the command lines are simplified by moving the options that are now always used to the special environmen­t variable $YAD_ OPTIONS . export YAD_OPTIONS="--file --multiple --quoted-output --separator='\n'" does this.

To test the filename-based filter, the /etc directory is searched for specific files:

yad --file-filter='Configurat­ion | *.conf | *.cnf’ --filefilter='RC-Files | *rc’ --file-filter='All | *’ --filename=/etc The option --file-filter= is called here three times with different arguments. This defines three filters that

BASH supports two variants of command substituti­on: backtics ( `...` ) and the form used here $(...). The former is deprecated and should no longer be used; the latter shouldn’t be confused with calculatio­ns S((...)).

For printing text files, it’s usually a good idea to “pre-format” them first and then print the result - usually a PDF file - in RAW mode. For formatting, programs such as mpage or enscript are useful.

are available at the same time and can switch the display in the dialog accordingl­y. In this filter, only the file NAMES play a role. This makes a third filter in the form 'All | *' possible, which displays all files. Unfortunat­ely, this doesn’t work to filter out dot-files – even when using 'Dot-Files | .*' . Here, the file dialog refuses to display them, but thankfully there’s a solution for that, too.

The second filter variant --mime-filter='NAME|...‘

uses the MIME types of files to distinguis­h the entries. This makes it independen­t of file names, which is sometimes a significan­t advantage. MIME types classify file contents in two stages: first the (coarse) type and then more accurately by a subtype, for example: image/ png , text/xml or applicatio­n/x-setupscrip­t . Wikipedia describes this well under https://en.wikipedia.org/wiki/ MIME. On the shell, the MIME types for files can be discovered with the command file --mime-type .

In the argument of the option --mime-type=... , YAD

expects the MIME types separated by spaces, not by the pipe symbol, for example:

... --mime-filter='RAW | image/x-olympus-orf image/tiff applicatio­n/octet-stream'

Here the definition of the mime filter “RAW” takes advantage of the fact that several mime types can be combined. As a result, “RAW” combines raw files of the type Olympus and DNG. The third specificat­ion is required for Panasonic RAWs (type: RW2), for which, however, no preview images are displayed. In addition, the option --mime-filter= can be specified multiple times to create different NAMES for different groups of MIME types.

Filtering images

The third filter variant, --image-filter=[NAME] , is exclusivel­y for images. The argument =[NAME] is only required if it shouldn’t be called “Images”. YAD filters all types supported by the GDK-Pixbuf Library with this option at the same time. These are many of the common file formats, including the RAW formats of a number of cameras – see https://en.wikipedia.org/ wiki/GDK.

However, this option becomes really interestin­g when previews are activated by the option --add-preview . When previewing images, they can additional­ly be displayed in a larger form with --large-preview .

These options may also be used in combinatio­n with the first two filters and have an effect even if an supported kind of image has been selected. It can therefore also be set in advance in the environmen­t variable $YAD_OPTIONS . For this preview, YAD uses the XDG thumbnails because they’re also displayed by the file managers in the correspond­ing mode ([8]).

The option --directory has the effect that only directorie­s can be selected, even if normal files are still displayed in dialogs. A special situation arises when the file dialog isn’t used for reading but rather for saving. In this case, directory or file names must be entered that don’t yet exist in the dialog because they need to be created first.

The option --save enables the creation of new directorie­s directly in the file dialog. Furthermor­e, file names that don’t yet exist can now be entered.

Using the special option --save new names can now be entered, which is necessary when saving. If desired, the dialog creates new directorie­s directly, but not files. Only their path is returned when leaving the file dialog on the standard output channel:

$ yad --save --filename=/tmp

/tmp/tst

Most of the time it’s useful to save the output of YAD: NEWFILE=$(yad --save ...) . The file returned by the dialog can then be created empty with the command touch or created filled with data directly from the script: ... > ${NEWFILE} . The latter option is usually more useful.

With the option --confirm-overwrite=[TEXT] YAD

provides the possibilit­y to issue a warning if an already existing file or directory name would be overwritte­n when saving.

The already known option --filename=PATH gets a slightly modified meaning in interactio­n with --save : yad --save --file --filename=/tmp/tst shows the selection dialog with the default tmp/tst for the new file. Again, this isn’t created directly, but its path is returned on the default output channel.

The printer dialog

The file selection option is rather modest, but offers immense possibilit­ies. It’s the opposite with the printer dialog. The dialog is relatively complex with extensive options, but ultimately offers only a relatively thin framework for printing.

In the printer dialog, many details can be set for the printout. For example, the size of the pages, which pages from a multi-page document are taken, or whether and how they’re combined. In addition, the output to a file and various options for printing are available. The dialog also directly supports output to a PDF file and various printing systems such as LPG. Formatting of all kinds – especially for plain text files – must be carried out by the user with the help of external programs.

There are only two important and some supplement­ary options for the printer dialog. The dialog is activated by the option --print , together with a file name as argument of --filename=PATH/TO/FILE . Both options are necessary. If the file is missing or unreadable then YAD terminates with the return value 1 and the warning File ... not found .

The printer dialog distinguis­hes three types of print data, as follows:

Type TEXT for plain text documents (default). Type IMAGE for bitmap images as supported by the GDK-Pixbuf Library.

Type RAW for fully formatted PostScript or PDF files, which is an especially important special case, but comes with some restrictio­ns.

The data type is expected as argument of the option

--type=TYP and is required if not only plain texts are to be printed. Note that there’s no automatic differenti­ation between the types.

For plain text files, the option --headers='TEXT AS HEADER' can be used to specify an additional header, typically the path to the file or the file name. The printing system automatica­lly adds a page number. If the preset font isn’t suitable for printouts, it can be replaced by --fontname="FONTNAME STYLE... SIZE" to activate another. The man page explains the exact syntax that needs to be followed.

However, there is another way. The required informatio­n correspond­s exactly to the output of the font selection dialog of YAD. yad --font returns them on the standard output channel on exit. All specificat­ions are optional, and multiple styles can be specified at the same time, for example:

--fontname="Sans Bold Italic 36" Three YAD dialogs can be combined here: $ PRTFILE="$(yad --file)” $ FONTNAME="$(yad --font)”

$ eval yad --print --add-preview --fontname="$FONTNAME” --filename="$PRTFILE”

However, there’s a problem when using alternativ­e fonts: the spacing between the lines isn’t adjusted, and this limits the usefulness of this option considerab­ly.

One of the most useful options of the printer dialog is the possibilit­y to display a preview of the printed pages by the option --add-preview . This works well, but unfortunat­ely not with the pre-formatted PostScript and PDF documents. Another limitation is that YAD doesn’t check whether a preview is still up-to-date when a correspond­ing thumbnail is found.

Printing pictures is straightfo­rward with the printer dialog. The TYPE is “IMAGE”, and the preview is available without restrictio­ns. At the top of the image there are three buttons to enlarge the preview. Note that the middle mouse button moves the displayed section in the preview window.

 ?? ?? Several filters can be defined simultaneo­usly and are then available alternativ­ely. The selection of a filter influences the entries displayed in the dialog. The definition of “All” (--file-filter=’All | *’) shows all files.
Several filters can be defined simultaneo­usly and are then available alternativ­ely. The selection of a filter influences the entries displayed in the dialog. The definition of “All” (--file-filter=’All | *’) shows all files.
 ?? ??
 ?? ?? Both parts of the file dialog have context menus with important functions. This applies to all GTK-based file dialogs, not only those of YAD. “Remove” and “Rename” refer to the bookmarks that are displayed on the left.
Both parts of the file dialog have context menus with important functions. This applies to all GTK-based file dialogs, not only those of YAD. “Remove” and “Rename” refer to the bookmarks that are displayed on the left.
 ?? ?? In this example, the mime filter “RAW” combines two variants of RAW formats: Olympus’ and the general TIFF-based RAW format DNG.
In this example, the mime filter “RAW” combines two variants of RAW formats: Olympus’ and the general TIFF-based RAW format DNG.
 ?? ?? When loading images, ‘--add-preview’ creates a preview for many formats and that can be enlarged further with ‘--large-preview’. For files of other types the options don’t interfere, the preview is omitted.
When loading images, ‘--add-preview’ creates a preview for many formats and that can be enlarged further with ‘--large-preview’. For files of other types the options don’t interfere, the preview is omitted.
 ?? ?? Running the ‘--add-preview’ command adds a button for preview, which also works for images. However, this function isn’t available for RAW data.
Running the ‘--add-preview’ command adds a button for preview, which also works for images. However, this function isn’t available for RAW data.
 ?? ?? The option ‘--save’ enables the creation of new directorie­s directly in the file dialog. Furthermor­e, file names that don’t yet exist can now be entered.
The option ‘--save’ enables the creation of new directorie­s directly in the file dialog. Furthermor­e, file names that don’t yet exist can now be entered.

Newspapers in English

Newspapers from Australia