Subversion (SVN) helper bash script to list repo dirs

Finding my way around SVN. So far I’ve created a repository to hold my WordPress theme files and miscellaneous scripts. The working directories are scattered around my home dir, and I found that I wanted a way to view the structure of the repo itself. You can do this with the svn list command:

svn list --recursive file:///path/to/your/svn/repo/dir

And you’ll get a list of all your directories and files. I thought it might be nice to only see the dirs, and then furthernice to specify the depth of dirs to browse, so I cobbled together the bash script below to accomplish this. It takes the output from svn list -R and prints only items that end with a forward slash, e.g.:

svn list -R file:///home/scarpent/src/svn | svn-dirs.sh -d 2

To produce the output:

bash/
bash/nautilus-scripts/
home-bin/
web/
web/mtf/

(I also created a script that runs svn list on my local repo and pipes to svn-dirs.sh, so I don’t have to type in the file:/// URL every time.)

How does it work?

First we use getopts to parse the command line options, which in this case is only -d, which lets us specify the max depth of directories we want to list.

Next, we use read to read the output produced by svn list. (Which becomes standard in — stdin — for our script.)

I initially thought of using the bash -d test to see if an item was a file or a dir, but I quickly realized that this wouldn’t work because these aren’t real files and directories. They’re part of the virtual SVN file system. Instead, I went by the last character, which is a forward slash for directories. We use ${#inpt} to get the length of the string, $(($len - 1)) to subtract one from that length, giving us the index of the last character, and then ${inpt:$last_char_idx} to extract that last character so we can compare it to “/”.

Finally, we determine how many slashes there are in the path — and thus the depth — by using this peculiar statement:

num_slashes=$(echo $inpt | tr -cd "/" | wc -c)

Which sends the SVN path in to the translate program, using options to discard anything that isn’t a forward slash, and then counts the remaining slashes with the word count program. (I found this neat trick in the Advanced Bash-Scripting Guide, along with a lot of other interesting string handling techniques. See resources below for more…)

And now, the script!

svn-dirs.sh script

#!/bin/bash

# svn-dirs.sh
# public domain script
# by Scott Carpenter, 2007

usage="svn-dirs.sh [-d] specify the depth of dirs to list"

max_depth=99
while getopts ":d:" opt
do
        case $opt in
                d  ) max_depth=$OPTARG ;;
                \? ) echo -e $usage
                     exit 1
        esac
done
shift $(($OPTIND - 1))

if [[ $(($max_depth < 1)) -eq 1 ]]; then
	max_depth=1
fi

while read inpt
do
	len=${#inpt}
	last_char_idx=$(($len - 1))
	last_char=${inpt:$last_char_idx}

	# tr = translate, discarding non-matches
	# then use wc to count chars, giving us
	# the number of slashes
	num_slashes=$(echo $inpt | tr -cd "/" | wc -c)	

	if [[ "$last_char" = "/" && $(($num_slashes <= $max_depth)) -eq 1 ]]; then
		echo "$inpt"
	fi
done

And that’s that. I hope you find this useful for browsing your SVN repository and getting an overview of what you have stashed away in there.

Resources


Buy @ Amazon

or Free Online


Buy @ Amazon

Related: SVN Nautilus Script Helpers

If you enjoyed this article, please subscribe for free!
Via the atom or rss feed, or enter your email address to get updates when new entries are posted:
(Your email will not be shared nor used for anything other than sending new posts. See the policies page for more about subscriptions and privacy.)

You can skip to the end and leave a response. Pinging is currently not allowed.

Comments

  1. Unix scripting is interesting in that there are many solutions to the same problem. Solutions come from perspective. I would have used awk to solve the same problem. Others would have used perl. Within bash, there are ways to solve this without calling external executables, such as wc or tr. Here’s what I would have done:


    svn list -R file:///home/scarpent/src/svn |awk -F/ '$NF ~ /^$/ && NF <= 2'

    awk is kind of like perl-lite. It is useful for parsing lines into fields at a separator. In this example, “/” is the separator. awk places the stuff between the separators into fields, which are addressable as $1, $2, etc. The number of fields is in the variable NF, and the contents of the last field are in $NF.

    So, the awk statement parses the line (record in awk parlance) into fields at “/”, then for records that have no contents in the last field (i.e. the ones with a trailing “/”), and have a number of fields less than or equal to 2, print the line. The print is implied.

    If you want to vary the number of fields to match, you can pass variables into awk using the -v switch:


    svn list -R file:///home/scarpent/src/svn |awk -v NUM=2 -F/ '$NF ~ /^$/ && NF <= NUM'

    which might make it more suitable for putting into a shell script.

  2. Excellent — thanks, Mario. This is the kind of stuff I like to hear about.

    I have a book on sed and awk on my desk at work and wish I had more time to work through it so I might get these ideas in advance. I also wish I had spent the last 10 years learning this stuff instead of wasting my time in Windows. :-)

    I figure it’s still good to struggle and figure it out one way or another, and try not to be paralyzed at the thought of all the better, quicker ways something might be done. I think I gained a little better understanding of how the pipeline works by figuring out how to use “read” in the bash script.

    Anyway, I appreciate you taking the time to explain alternate options. I always want to understand my options better and pick the most suitable approach.

  3. This may be premature optimization in this case, but in Bash you can use arithmetic inside parameter expansion. This can be used to get the last character in a variable, which you did in three steps.

    ${inpt:${#inpt}-1}

    This expands into the last character of inpt using only one parameter expansion. As a bonus (?), it makes the code almost as unreadable as Perl. :)

  4. Excellent — thanks, Christopher. I’m still pretty clumsy with bash, which may be mostly me needing to learn more about the basics, but I think also bash has its limitations for scripting.

    I’m learning Python now, and imagine my future attempts at utilities like this will be done with it instead.

    But I still think bash is awesome!

You can follow any responses to this entry through the
comments feed.

Say Your Say

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>

By submitting your comment here, you agree to license it under the same Creative Commons Attribution-ShareAlike 3.0 License as the movingtofreedom.org web site. Please see policies for more information about comments and privacy.