How do I djvubind only files that are in ls | grep -P "page\\d\\d\\d.tif"
?
1 Answer
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 thedjvubind
command will not work, becausedjvubind
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 evengrep
.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 whilegrep
certainly may be used for this purpose, your approach has the disadvantage of selecting some files with quite different names, likerampage999.tiffany's.revenge.mp3
. (You could fix that by passinggrep
the-x
flag, but really you don't needgrep
at all for this.)
Selecting the Desired Files
There are two especially popular methods for selecting files that match a particular pattern:
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.