Using xargs, sed and pipes
Upon migrating my blog to new engine, I had to rename bunch of article files.
So basically to move files from nested directories into
source directory, downcasing and adding a prefix of year-month-day.
find source/20??/**/*.markdown | xargs -n1 sh -c 'echo $0 && echo $0 | tr "[:upper:]" "[:lower:]" | sed -e s/\\//-/g -e s/^source-/source\\//' | xargs -n2 mv
In the first line, we list all article files, using wildcards.
Then we’re piping the output to
-n1 switch, and a command. This will invoke the command for every (
-n1) line passing it as argument. The trick is, command to invoke is actually a new shell process with its own instructions passed after
In the subshell, we first print the original path (
$0, because it was the argumant passed to the shell). Then the path is processed:
tr "[:upper:]" "[:lower:]"converts it to lower-case letters
- we’re using sed with two
s/\\//-/g- replaces every occurence of
-. I had to use
\\/because it is interpolated to string, being an argument to
s/^source-/source\\//- restore first slash after
- no more pipes so processed path is printed to stdout.
Now we have multiple lines of paths, original, then processed and so on:
source/2012/09/17/Using-xargs-and-sed.markdown source/2012-09-17-using-xargs-and-sed.markdown source/2012/08/04/Checker-gem-for-ruby-rails-development.markdown source/2012-08-04-checker-gem-for-ruby-rails-development.markdown
Piping that to
xargs -n2 mv will invoke
mv passing consecutive pairs of lines, which is just what we wanted!
mv source/2012/09/17/Using-xargs-and-sed.markdown source/2012-09-17-using-xargs-and-sed.markdown
Have a better / more obvious solution? Let me know in the comments. Meanwhile, <3 UNIX.