1

How do I djvubind only files that are in ls | grep -P "page\\d\\d\\d.tif"?

1 Answer 1

2

Hurried readers can skip down to Putting Everything Together and read just that section--but for users new to the topic I suggest starting from the beginning.

Basic Principles

Running djvubind so it only uses files named pageNNN.tif (where each N is some digit) is in one way significantly more complicated than you might be thinking, while in another way is a bit less complicated.

  • Passing the names of just the desired .tif files to the djvubind command will not work, because djvubind takes a directory as its argument, and insists on trying to use all the files directly contained in that directory.

    One way to get around this is to build another directory of hard links pointing to files in the directory you started with, running djvubind on that directory, then (optionally) removing it. I will present that method in this answer.

    Normally, for this sort of thing, symbolic links would be preferred to hard links. However, djvubind apparently skips over symbolic links automatically, refusing to process the files they point to. (There doesn't seem to be any option to change this behavior, but if someone knows of a way, I--or they--can edit this answer.)

  • But it is less complicated in that you do not need to invoke ls or even grep.

    Except for some rare situations where the only goal is to show a directory listing to the user, it is generally best to avoid parsing the output of ls. And while grep certainly may be used for this purpose, your approach has the disadvantage of selecting some files with quite different names, like rampage999.tiffany's.revenge.mp3. (You could fix that by passing grep the -x flag, but really you don't need grep at all for this.)

Selecting the Desired Files

There are two especially popular methods for selecting files that match a particular pattern:

  1. shell globbing and a for loop
  2. the find command (which accepts similar globbing syntax)

I'll use the first way in this guide, and show the commands for the second way at the end.

First, I suggest composing and trying out a command just to show the names of the files we want to operate on. This is to help avoid mistakes--you'll see if you're selecting the files correctly or not. To do this, you can run printf '%s\n' filename for each one. (For the real thing, you'll replace printf '%s\n' with a different command.)

for x in page[0-9][0-9][0-9].tif; do printf '%s\n' "$x"; done

Note that the glob (page[0-9][0-9][0-9].tif) is unquoted, as the shell must expand it, then loop through the expanded list. (Testing will look something like this, though your output will be longer if you have many files. You should be able to see how only the correct files are selected.)

Putting Everything Together

Now for the real thing. Make a directory to store the hard links:

mkdir page-links

Populate the new directory with hard links to the desired files:

for x in page[0-9][0-9][0-9].tif; do ln "$x" "page-links/$x"; done

Run djvubind on the newly populated page-links directory:

djvubind page-links

Optionally, remove the directory of hard links:

rm -r page-links

It will look something like this.

If you prefer find...

To use find instead of shell globbing and a for loop:

  • use -mindepth 1 to prevent the containing directory from being considered as a possible match,
  • use -maxdepth 1 so that only files directly contained in the current directory (not those in its subdirectories) are matched, and
  • do quote the pattern, as it must be passed unexpanded by the shell to the find command (which then performs the matching).

List the files:

find . -mindepth 1 -maxdepth 1 -name 'page[0-9][0-9][0-9].tif'

Without specifying any action, the default -print action is used, listing the files you have selected. Results will be preceded by ./, but that won't cause any problems here.

After creating the target directory (mkdir page-links), populate it:

find . -mindepth 1 -maxdepth 1 -name 'page[0-9][0-9][0-9].tif' -exec ln {} page-links/{} \;

You don't have to quote {}, though some people like to do so because it clarifies (to humans) that it is not a brace expansion, and perhaps it is necessary to do so when invoking find from some non-Bourne-style shells, if they use different brace expansion syntax. Note that, whether or not you quote it, find will behave the same--including for files with spaces in their names. (find never sees the quotes, as they are removed by the shell before find runs. The misconception that quoting {} has something to do with the way find's -exec action passes filenames to commands is why I don't quote it.)

After that, running djvubind (and optionally removing the page-links directory afterwards) will of course work exactly the same way.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .