views:

314

answers:

4

I'm writing a simple ruby sandbox command-line utility to copy and unzip directories from a remote filesystem to a local scratch directory in order to unzip them and let users edit the files. I'm using Dir.mktmpdir as the default scratch directory, which gives a really ugly path (for example: /var/folders/zz/zzzivhrRnAmviuee+++1vE+++yo/-Tmp-/d20100311-70034-abz5zj)

I'd like the last action of the copy-and-unzip script to cd the calling shell into the new scratch directory so people can access it easily, but I can't figure out how to change the PWD of the calling shell. One possibility is to have the utility print out the new path to stdout and then run the script as part of a subshell (i.e. cd $(sandbox my_dir) ), but I want to print out progress on the copy-and-unzipping since it can take up to 10 minutes, so this won't work. Should I just have it go to a pre-determined, easy-to-find scratch directory? Does anyone have a better suggestion? Thanks in advance for your help. -Erik

+1  A: 

A process cannot change the environment of its parent process, so you will have to do some action in the parent.

You could have your users source a shell script, and that script calls the ruby program and cd's somewhere. When you use your shell's source command (. or source), that affects the current process.

glenn jackman
+3  A: 

You could die into a new shell that sits at your scratch dir, but I am having trouble understanding the point of all this. If your users are going to edit these files, then i suppose they either want to keep them or you are planning on working with the modified files. In the first case, put the files in a sensible location and you won't have to worry about your users finding them (current working directory). In the second case, spawn a subshell for your users that sits in the scratch dir and instruct them to edit the files. When the subshell exits you can continue to process your files from the same ruby program.

Segfault
Outputting to cwd isn't bad, but one of the reasons for copying and unzipping is to transfer the data to a local filesystem with much better latency, although there's no rule that states the user can't make their own scratch directory. A more intuitive solution might be to default to a known scratch directory (/tmp, for example) and tell them to look there. I'd like to do it the right way (mktmpdir) but I think that's not designed to persist for longer than the run of a program (not hours like I'd need it to.)
Erik Kastman
+1  A: 

As, glenn jackman notes, a child process can not change its parent's current working directory (or environment variables, etc.). Unless you count violating the parent process with a debugger…

A process run as part of a command substitution can write to stderr to provide output to the user while the stdout output is captured by the command substitution:

cd "$(sandbox whatever)"

Where the sandbox command sends most of its output to stderr, and just the final ‘directory to chdir to’ to stdout. If sandbox was a shell script, you could do it like this:

#!/bin/sh
newdir="$(mktemp -dt sandobox)"
{
# do whatever, in a sub-shell
# use a group command (or change the braces to parens to use a sub-shell) to
# capture all stdout and send it to stderr 
} 1>&2
echo "$newdir"

I am sure something equivalent could be done in Ruby.

Chris Johnsen
A: 

Create your temp directory from your wrapping shell script first and then pass it as a command line argument to your Ruby script.

Mladen Jablanović