I have a git clone of etckeeper, and I'm trying to rename all files and directories with etckeeper
in the name to usrkeeper
. For example, ./foo-etckeeper-bar
should be renamed to ./foo-usrkeeper-bar
.
Finding the relevant files is trivial:
% find . -path '*etckeeper*' -print
However, I can't figure out how to actually do the renaming. I tried combining xargs
with mv
:
% find . -path '*etckeeper*' -print0 | xargs -0 -n 1 -J % bash -c mv % '$(echo' % \| sed \"s/etckeeper/usrkeeper/\" \)
For readability, the non-escaped second half reads: xargs -0 -n 1 -J % bash -c mv % $(echo % | sed "s/etckeeper/usrkeeper/" )
. The idea behind it is that we use $()
to pipe the filename through sed
, which is used to do the replacement.
The issue here is that bash -c
requires the command to execute to be a single string. After that, it starts interpreting arguments as positional parameters. I could quote the whole thing:
% find . -path '*etckeeper*' -print0 | xargs -0 -n 1 -J % bash -c 'mv % $(echo % | sed "s/etckeeper/usrkeeper/g" )'
But now xargs
won't replace %
. How can I solve this? (Also, as a side note, the above will fail if there's a file containing etckeeper
in the name in a directory containing etckeeper
in the name, because the directory will be moved before the file.)