I'm quite familiar with Dir.chdir("/xyz")
Unfortunately, this changes the directory of the process, but not actually the directory of the user. I'll make the following example to illustrate my need.
$~/: ruby my_script.rb
CHANGING TO PATH FOR USER NOT SCRIPT
$/Projects/Important/Path: pwd
$/Projects/Important/Path
See? I need the script to change the user's path. Performing system/backticks/Dir.chdir all adjust the process path, and end with the user sitting where they started, instead of the path I want them.
From what I've read exec was the way to go, since it takes over the existing process... but to no avail.
You can't, but you can do something which might be good enough. You can invoke another shell from ruby:
Dir.chdir("/xyz")
system("bash")
Running this will create a new bash process, which will start in the /xyz directory. The downside is that changing this process will bring you back to the ruby script, and assuming it ends right away - back to the bash process that started the ruby script.
Another hack that might work is to use the prompt as a hackish hook that will be called after each command. In the ruby script, you can write the new directory's path somewhere that can be read from both bash and ruby(for example a file - but not an environment variable!). In the PROMPT_COMMAND function, you check that file and cd to what's written there. Just make sure you delete that file, so you don't get automatically cded there after every command you run.
Related
so I have a bash script right now which automates the git process for me. I have made the shell script accessible from everywhere. I want to give the script a command like "ctdir" instead of typing in "intilize_directory.sh" every time. Is there a way to make this possible?
There are (at least) three ways to do this:
First, if it's on your path, you can simply rename it to ctdir.
Second, you can create an alias for it in your startup scripts (like $HOME/.bashrc):
alias ctdir='initialize_directory.sh'
Third, you can create a function to do the work (again, defining it in your startup scripts):
ctdir() {
initialize_directory.sh
}
Just remember to make sure you load up your modified startup scripts after making the changes. New shells should pick the changes up but you may need to re-source it manually from an existing shell (or just exit and restart).
Agreed with #paxdiablo, the best way is to create an alias.
Following steps will work in Linux:
Naming the alias.
Type the following at the command line:
alias ctdir='initialize_directory.sh'
Edit bashsrc file.
This file is usually present at your home directory.
Add at the alias mentioned in step 1 at the end of the bashsrc file to make them permanent and reusable in every session.
vi ~/.bashsrc
I'm working on an interactive Ruby script, which build and packages resources. In the middle of the process, I'd like to drop into an interactive shell, but pre-cd'd into a specific working directory, as well as with an explanatory message (CTRL-D to continue). The interactive bash + given initial command is what's problematic.
Per the answer for doing something like this in Bash, given at https://stackoverflow.com/a/36152028, I've tried
system '/bin/bash', '--init-file', '<(echo "cd ~/src/devops; pwd")'
However, bash runs interactively but completely ignores the '<(echo "cd ~/src/devops; pwd")' section.
Interestingly system '/bin/bash', '--init-file complains if no argument is given, but literally anything runs bash, but with no initial command.
*Note that (--rcfile instead of --init-file) has the same effect.
Change the working directory of the Ruby script first, so that bash inherits the correct working directory.
curr_dir = Dir.pwd
Dir.chdir("#{Dir.home}/src/devops")
system "/bin/bash"
Dir.chdir(curr_dir) # Restore the original working directory if desired
Oh, this is probably far better (you can probably guess how little familiarity I have with Ruby):
system("/bin/bash", :chdir=>"#{Dir.home}/src/devops")
I realize that:
Dir.chdir("/path/to/some/dir/")
will temporarily change to the appropriate directory. My question is: is there any way to make this persistent? When I exist the script, I remain in the same directory as I started. I have also tried execute commands with backticks, but it seems like everything is run in a new shell.
Does Ruby have the ability to change my shell's directory?
No, it is not possible.
In fact, no child process can change the current working directory of its parent process.
When you execute a script (or any program) from your command shell you are actually doing a "fork/exec" pair, which means you create a "child process" which is separate from your shell "parent process" in many ways. The child can make changes to its own environment but cannot (typically) change the parent environment.
One small correction:
Dir.chdir("/path/to/some/dir/")
changes the directory for the rest of the script execution. A temporary change is possible with the block version of the command.
And to answer your question:
No, it is not possible.
Even the following script does not work:
puts Dir.pwd
puts `cd ..`
puts Dir.pwd
The cd-command in backticks starts a new environment, so your parent's shell will not change the directory.
I have a Ruby script that I wrote that sorts some files in a jumble of directories based on it's file extension. It would be very difficult to sort it using a GUI, and its easier for me to just put the file in the topmost directory and let the sorter do the work.
Problem is, I'm a bit of a noob to unix scripting. What I want to be able to do is be able to run that sorter script from anywhere on my computer, without having to
cd Desktop/Whatever/Foo
ruby sorterscript.rb
just write sortfolders at the commandline and have the program be run.
I've tested the script many times, and it works fine, I just want a bit more convenience.
Bonus: If possible, and not too difficult, it would be even better if I could have the program run, say, every hour automatically.
As far as your first question goes, you need to do couple of things:
Add a shebang line to your script (make it the first line of the script):
#!/usr/bin/ruby (or whatever the path to the Ruby interpreter's executable is, I forget its exact location)
Make the script executable, either via the Finder's "Get Info" context menu, or via the command line, for example:
chmod 755 my_script.rb
Add the directory location of your script to the PATH environment variable to OS X's launchd.conf file, as described here. You need to add this line:
setenv PATH /path/to/my/script:$PATH (substitute the real path to your script)
As far as your bonus question goes, you can use cron to set up a recurring job. I never really do this, but here's Apple's cron man page to get you started.
I'm trying to change the directory of the shell I start the ruby script form via the ruby script itself...
My point is to build a little program to manage favorites directories and easily change among them.
Here's what I did
#!/usr/bin/ruby
Dir.chdir("/Users/luca/mydir")
and than tried executing it in many ways...
my_script (this doesn't change the directory)
. my_script (this is interpreted as bash)
. $(ruby my_script) (this is interpreted as bash too!)
any idea?
Cannot be done. Child processes cannot modify their parents environment (including the current working directory of the parent). The . (also known as source) trick only works with shell scripts because you are telling the shell to run that code in the current process (rather than spawning a subprocess to run it). Just for fun try putting exit in a file you run this way (spoiler: you will get logged out).
If you wish to have the illusion of this working you need to create shell functions that call your Ruby script and have the shell function do the actual cd. Since the functions run in the current process, they can change the directory. For instance, given this ruby script (named temp.rb):
#!/usr/bin/ruby
print "/tmp";
You could write this BASH function (in, say, you ~/.profile):
function gotmp {
cd $(~/bin/temp.rb)
}
And then you could say gotmp at the commandline and have the directory be changed.
#!/usr/bin/env ruby
`../your_script`
Like this?
Or start your script in the directory you want it to do something.
Maybe I don't get your question. Provide some more details.