While the syntax is daunting at first, and escaping will be an eternal problem, eventually it starts making sense and you'll be able to do anything in seconds. The work in the post becomes trivial:
mv app/views/foo/**/* app/views/
sed -i 's/\([a-z]*\)foo_\([a-z]*\)path/\1\2path/' app/views/**/*
or in a more imperative (and probably less efficient) style: for file in app/views/foo/**/*; do
sed -i 's/\([a-z]*\)foo_\([a-z]*\)path/\1\2path/' $file
new_path=$(sed 's,foo/,,' <<< $file)
mkdir -p $(dirname $new_path)
mv $file $new_path
doneBut it becomes a self-renforcing loop: the more you rely on this toolbox, the more problems you create that are best solved with the same tools and the particular mindset they promote. But for work-related tasks, throwaway code rarely is: your code becomes part of your infrastructure and you have to make it work reliably now and later.
After some years, things are not so fun anymore: assembling strings means escaping/quoting characters for different formats and languages. With shell scripts, the path of least resistance is unsafe and introduce many unneeded assumptions.
For example, in the above code, globbing in app/views/foo/... in the "for" expression will not work if you have spaces in file names. And if you can get it right, $file is not inside double-quotes; mv will erase any previously existing file. And even though some of the assumptions are valid in context, will they always hold?
In order to make them hold, people tend to adapt their problem to fit their tools, not the other way: file names are always in a well-known ascii range, with no space but a specific separator and zero-padding (e.g. myfile_00020, because files are sorted lexicographically). Unless you are willing to use json/xml tools, data is cut into pieces of strings: records are line-separated; each field is colon-separated, each subfield is comma-separated, etc (recursive CSV). And one day, that field which always contain dates in YY/DD/MM format (why not ISO-8601?) starts having a time too, formatted HH:MM. After a painful recovery of trashed data, you add "just one more script" to properly escape colons.
Languages are designed with specific goals in mind and writing complex programs is not what scripting languages are optimized for. I now prefer to use language with data-structures, functions, objects, namespaces: less use for strings and regexes. If I try to write onto an existing file, I will be warned (or I can explicitely allow overwriting). Paths are organized as os-independant trees, etc: there are better interfaces to the facility provided by the OS. Coincidently, the need for scripts gradually reduced, at least the one I need to save (I still chain programs on the command-line).
Problem with shell is that you need to solve same problems again and again. This is why I wrote "bash-modules" script (https://github.com/vlisivka/bash-modules), which allows to write module with common code and then just do ". import.sh module" from script or command line.
find app/views/foo -depth -type f | while read f; do mkdir -p $(dirname ${f##foo/}); sed <"$f" >"${f##foo/}" -e s'/\([a-z]*\)foo_\([a-z]*\)path/\1\2path/g'; echo rm "$f"; done perl -pi -e 's{(.*?)foo_(.*?)path}{$1$2path}' app/views/*/*I wrote this article, because when I was a very new developer, I was learning a lot more Rails than I was Ruby. It had never occurred to me to use Ruby for scripting until I paired with a well rounded Rubyist. With the influx of people learning Rails, I've talked to many people who know much less about Ruby than I did when I was starting out. This isn't mentioned in the article at all, but it was definitely something I thought about when I decided to write it. Honestly, if this helps push one new dev to go out and decided to actually learn some extra Ruby outside of Rails, I'll be happy.
I agree 100% about the shell comments. I know enough shell to do my job, but for me it's quicker to write a Ruby script. Not saying it's the most efficient way, but it is a way, and it's more efficient than doing it by hand. As much as I'd love to be a unix shell wizard, I'd rather be improving my Javascript, or learning more Elixir.
As for the namespace vs scope: The example was just a way to end up with a scenario where we needed to change some text. Plus, for clarity, if I don't want my controllers or URL namespaced, my routes and files should reflect that, not work around it with a scope unless necessary for some reason(in my opinion). I actually later thought that I should've used the script on a JS project, just to help highlight the fact that this is totally independent of Rails.
I wonder if it would be an interesting project to comb though it all and see if any useful tools could be extracted. Probably not, like the code in this blog most of my one-offs are unashamedly terrible.
This was inspired by http://samba.org/ftp/tridge/talks/junkcode.pdf - you may recognise the author!
I never intended this to see the light of day, but since the topic warrants it, here is a python one-liner I'm using to put the indices of combinations of subsets into one list:
combos = map(list,reduce(lambda x,y: x+y,[[c for c in itertools.combinations(range(8),i)] for i in range(1,9)]))
yuck. These things usually end up as a result of testing and tweaking in an interactive shell.
that may come off as mean/rude towards the author, but I don't mean it so. I do shit like this all the time because I don't know every little trick with the languages/frameworks I'm using, it's impossible to know it all unfortunately.
I don't think I have ever looked at code I have written more than a few months ago and NOT found a bunch of things I could have done much simpler if I had just known about some feature or trick. I have stopped feeling bad when that happens; now, I figure that the day I stop experiencing that is the day I am no longer getting better as a programmer.
Emacs macros are wonderful too.
Now i am still convinced that regexp are still usefull but you will not get it right for the first try due to syntax corner case. The best solution in my opinion is to have easy to use parsers including one for your main programming language.
Actually i emacs with its macro feature (not elisp) + racket with regexp (didn't mention earlier but having a strong repl for this kind of incremental script is also a must to have) and sometimes parsers.