I'm trying to run the expand shell command on all files found by a find
command. I've tried -exec and xargs but both failed. Can anyone explain me why? I'm on a mac for the record.
find . -name "*.php" -exec expand -t 4 {} > {} \;
This just creates 开发者_开发百科a file {}
with all the output instead of overwriting each individual found file itself.
find . -name "*.php" -print0 | xargs -0 -I expand -t 4 {} > {}
And this just outputs
4 {}
xargs: 4: No such file or directory
Your command does not work for two reasons.
- The output redirection is done by the shell and not by
find
. That means that the shell will redirectfind
s output into the file{}
. - The redirection would occur immediately. That means that the file will be written even before it is read by the
expand
command. So it's not possible to redirect a command's output into the input file.
Unfortunately expand
doesn't allow to write it's output into a file. So you have to use output redirection. If you use bash
you could define a function
that executes expand
, redirects the output into a temporary file and move the temporary file back over the original file. The problem is that find
will run a new shell to execute the expand
command.
But there is a solution:
expand_func () {
expand -t 4 "$1" > "$1.tmp"
mv "$1.tmp" "$1"
}
export -f expand_func
find . -name \*.php -exec bash -c 'expand_func {}' \;
You are exporting the function expand_func
to sub shells using export -f
. And you don't execute expand
itself using find -exec
but you execute a new bash
that executes the exported expand_func
.
'expand' isn't really worth the trouble. You can just use sed instead:
find . -name "*.php" | xargs sed -i -e 's/\t/ /g'
精彩评论