Working with the Z shell

Some days ago I thought it would be a good idea to copy the files I have created on my office computer to my laptop. This seems to be an easy task. I just had to find all recently changed files and copy them, if they are newer than any versions found on my laptop. I thought of a combination of the find command with rsync. After a quick look at the manual pages I typed the following command:

rsync -avuR `find ./* -user maha -mtime -300 -type f` maha@sputnik:

This means: first, find all the files (and only files, -type f) that belong to user maha and were modified within the last 300 days, then archive them (rsync -a) with their relative pathnames (-R) to maha’s home directory on sputnik (my laptop) without deleting files or overwriting existing newer versions (-u), and be verbose (-v). This worked fine for all file names which didn’t contain special characters or blanks. But unfortunately, I had quite some file names with blanks, umlaut characters, etc., and the find command does not escape special characters. :-(

I remembered that I usually use the Z shell on my computers, which makes use of extensive globbing that can tackle with blanks and other special characters. The commands became a lot easier, the only disadvantage being that I had to use two commands to get all files:

rsync -avuR ^[.]*/*(mM-10.u:maha:) maha@sputnik:

This command catches all files in subdirectories not beginning with a dot, since I wanted to exclude files in my .mozilla directory and the like; mM-10 stands for modified within the last 10 months (of 30 days), the dot prescribes that only files are to be transferred and they have to belong to user maha (I later found out that it works even without the u before :maha:).

rsync -avuR ^[.]*(mM-10.u:maha:) maha@sputnik:

This command catches all files in my home directory not beginning with a dot. (The find command ignores dotted files by default, Z-shell globbing doesn’t, which may sometimes be an advantage.)

I find the wildcard syntax of the Z shell quite straight forward. Unfortunately, I didn’t find out how to condense the two commands into one. Anyone got an idea?

It is very easy to avoid complicated find-command constructions in the Z shell. As a comparison of computer shells shows, Bash has caught up a lot, but I still prefer the command line completion of the Z shell and its easy-to-use command history: if I have begun to type a command I can browse through all variants of that command I typed in earlier (by just hitting the up-key). This is very useful for me who always forgets how commands work.

4 Responses to “Working with the Z shell”

  1. erdgeist says:

    Dear Maha,

    maybe the command line

    find ./* -print0 -user maha -mtime -300 -type f | \
    rsync -avuR –files-from=- –from0 maha@sputnik:

    is what your are looking for.

    Regards

    erdgeist

  2. Keks says:

    Hi Maha,

    just combine the two commands this way:

    rsync -avuR ^[.]*/*(mM-10.u:maha:) ^[.]*(mM-10.u:maha:) maha@sputnik:

    Most shell commands are capable of handling multiple (source) parameters. This is important, because wildcards are expanded by the shell.

    Regards,
    Oliver aka Keks :-)
    http://www.blitztarif.de/

  3. maha says:

    erdgeist, you are a real find-ling, this is indeed the solution for the find variant, you just have to specify the source (even with –files-from, with this option the -R is not needed anymore):

    find ./* -print0 -user maha -mtime -300 -type f | \
    rsync -avuR –-files-from=- –-from0 . maha@sputnik:

    but the zshell solution looks more elegant to me.

  4. maha says:

    Keks: you are so right, how could I have overlooked that? really cool solution

Leave a Reply