[sclug] Couple of questions

Roland Turner raz.fpyht.bet.hx at raz.cx
Sat Oct 25 09:05:34 UTC 2003


On Mon, Mar 03, 2003 at 02:13:45PM +0000, Andy Arbon wrote:

> Hello,

Greetings,

> 1) Is there a way to get an Xterm to notice that it has been resized? If
> ~ I start an Xterm and then maximise it it sometimes completely mangles
> input lines that would have been too long for the un-maximised Xterm.
> It's hard to describe; if you don't see what I'm on about I'll try and
> write a better description.

As others have pointed out,

	$ eval `resize`

should solve your problem, but it also should not arise in the
first place. You didn't mention which application you were
using that failed to act on the resize notification that xterm
generated; not a shell, surely?

(Embarrassing gotcha: if you resize while in, say, vi then vi
will process the resize notification. When you return to your
shell, your shell may not double check the terminal size and
thus, until you resize again, not have a correct understanding
of the terminal size. In bash's case

	$ shopt -s checkwinsize

will fix this; do a

	$ shopt -p | grep checkwinsize

to check its current value before blindly changing it.)

> The other problem:
> 2) I have 2 text files each containing a list of files. (say txt1 and
> txt2). All files in txt1 are also in txt2, but there are files in txt2
> that are not in txt1. I want to be able to separate out the files which
> do not appear in both.. What is the best way?
> 
> Diff doesn't seem to do it (unless there is some weird combination of
> parameters that makes it work?).

Others have pointed out the use of sort and diff, in fact grep
can do it by itself more simply, without diff's output polution.

	$ grep -F -v -f txt1 txt2

Roughly, this subtracts (-v) all instances of patterns in file
(-f) txt1 from file txt2. You don't want any regexp characters in
filenames to be interpreted, particularly if txt1 is the result
of a "find ." or similar, so use fixed-strings (-F or fgrep) mode.

There is a gotcha here too, although one that you can almost
certainly safely ignore. For a long time, UNIX text tools assumed
that no filenames contained whitespace, despite the filesystem
explicitly permitting a filename to contain any sequence of bytes
other than 47 (ASCII slash) or 0. Most of the GNU tools can now
use 0 as a seperator for almost everything (find -print0, xargs -0,
sort -z, perl -0) but the support in grep is incomplete. Use of 0
as an output seperator (-Z or --null) has been present for a
while; its use as an input seperator (-z or --null-data) appears to
be newer, so much so that it's not mentioned in the manpage.
Sadly there does not appear to be support for a null-seperated
list of patterns (your txt1) in GNU grep. In practice, this is a
very small problem; even if you have filenames which contain
whitespace, it is not likely that they contain newlines; -f will
only be confused by the latter case. It would be nice to have
"guaranteed to work" solution though :-) Null seperating txt2 but
not txt1 _does_ work; working out how is left as an exercise for
the reader :-)

All of this dances around the "what are you trying to achieve?"
question. If you only mention the narrow implementation question
that you are stuck on, it is possible (likely!) that you'll
exclude the possibility of better but completely different
approaches to your broader goal being suggested to you.

> Subject: Re: [sclug] Couple of questions
> Date: Mon, 03 Mar 2003 16:15:59 +0000
>
> This script should build a command line for 'find' that searches all of
> the paths in $PATHS, exculding those listed in $EXPATHS and prints every
> file found.

This short description helped!

OK, where to start?

- My guess is that something was barfing around the escaped
  parentheses, so the first change is to start FINDEX empty, and
  to not add the -false... to it at all; as the start and end of
  your FINDEX string are fixed, they can be factored out into the
  find line itself, thereby removing the parentheses from the
  quoting problem entirely. In general, if you are building up a
  command string in a for loop (sometimes you have little choice),
  put as little in the generated string as possible; less chance
  for errors.

- Next, you have the -prune option in the wrong place. the
  '-o -false' guarantees that -prune will never be evaluated,
  which isn't what you need.

- Next, $FINDEX-false, even if it's legitimate, is rather
  difficult to read. It can be readily disambiguated with
  ${FINDEX}-false.

- Finally, there is (now) no need to quote FINDEX on the find
  line; in fact you almost certainly don't want to.


#! /bin/sh
 
PATHS="/usr /var /bin /sbin /opt /lib /boot /etc"
EXPATHS="/usr/portage /var/wine /var/tmp/ccache /var/log /var/cache"
 
FINDEX=
for path in $EXPATHS
    do FINDEX="${FINDEX}-path $path -o "
done
 
find $PATHS \( $FINDEX -false \) -prune -o -print


BTW, I did not know the answers to start with; trimming your
script to try simpler problems until I had a script that did what
I expected and then incrementally adding pieces until the whole
script was there was my approach. If you have something that
doesn't work, just futzing about with quotes will usually not
work either. It is my experience that simplifying to a working
solution (to a simpler problem) and _then_ incrementally
elaborating always works better. (Move from the known to the
unknown.)

- Raz



More information about the Sclug mailing list