The context of this question is the hg-ssh script. It is helpful but not critical to know something about Mercurial. This script sets up a forced command using public keys so the given public key setup on the server will only allow the owner of the corresponding private key to push to a permitted set of repositories on the server. This forced commands is usually prefixed to the public key in the file ~/.ssh/authorized_keys on the server. With regard to this permitted set, the documentation before the script in the link above says:

You can use pattern matching of your normal shell, e.g.:
command="cd repos && hg-ssh user/thomas/* projects/{mercurial,foo}"

The idea is to permit only pushing to repositories on the server that match this pattern. I've been using hg-ssh with the forced command

command="cd /srv/hg && /usr/local/bin/hg-ssh * */* */*/* */*/*/*",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa [...]

to match all repositories (up to some number of path components) under /srv/hg, using shell globbing. I belatedly realized that it is not matching paths which contain components starting with .. My current non-working example is the MQ repository /srv/hg/faheem/bixfile/.hg/patches. So, my question is, can I select a pattern that corresponds to all paths? I would prefer to use shell globbing, which are less of a headache than regular expressions in general, but I'd take a regular expression if globbing is not an option.


1 Answer 1


For recursive matching, the right tool is often find. Since you want to match all files in the current directory and its subdirectories recursively, but only down to a certain depth, specify -maxdepth. This isn't in POSIX, but exists on all current *BSD and in GNU find (Linux, Cygwin) and in Busybox (embedded Linux) so it's a safe bet that you have it. -exec … {} + is a relatively recent addition to POSIX, but it's been in GNU and FreeBSD/NetBSD/OSX for a while now.

cd /srv/hg && find . -type d -maxdepth 3 -exec /usr/local/bin/hg-ssh {} +

(I added -type d because you seem to want to match directories only, even though your attempt with * */* etc. matches files of all types.)

  • Ok, thanks. How would this look exactly, in the context of the script as posted above, ie command="cd /srv/hg && /usr/local/bin/hg-ssh * */* */*/* */*/*/*",no-port-forwarding,...? Does everything up to the curly brackets go inside the command? Also, really, the idea is to match only the directories, not the files, since a repository can only correspond to a directory, and not a file. Jul 3, 2011 at 21:20
  • @FaheemMitha Everything, from cd to +, is the shell command. I copied what you did, matching all files regardless of type. If you want to match only directories, add -type d before -exec. But I wonder if this is really what you want (note that I know nothing about hg-ssh): are you looking for .hg directories? Jul 3, 2011 at 21:25
  • No, all directories are possible Mercurial repositories. The example I gave (/srv/hg/faheem/bixfile/.hg/patches) is the special case of a MQ repository, which lives inside the .hg directory corresponding to another Mercurial repository. I tried it and got remote: find: Expected a positive decimal integer argument to -mindepth, but got '-maxdepth'. Can one just leave mindepth out, or does it need to be given a number? Jul 3, 2011 at 21:42
  • It works if I take out -mindepth, but does it then default to mindepth 1? I'm currently using command="cd /srv/hg && find . -maxdepth 4 -type d -exec /usr/local/bin/hg-ssh {} +". Jul 3, 2011 at 21:50
  • @FaheemMitha I meant -mindepth 1 to exclude . (depth 0), but I guess you want to include it? So no -mindepth. Jul 3, 2011 at 21:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.