问题
I have the following alias in my .aliases:
alias gi grep -i
and I want to look for foo
case-insensitively in all the files that have the string bar
in their name:
find -name \*bar\* | xargs gi foo
This is what I get:
xargs: gi: No such file or directory
Is there any way to use aliases in xargs, or do I have to use the full version:
find -name \*bar\* | xargs grep -i foo
Note: This is a simple example. Besides gi
I have some pretty complicated aliases that I can't expand manually so easily.
Edit: I used tcsh
, so please specify if an answer is shell-specific.
回答1:
Aliases are shell-specific - in this case, most likely bash-specific. To execute an alias, you need to execute bash, but aliases are only loaded for interactive shells (more precisely, .bashrc
will only be read for an interactive shell).
bash -i runs an interactive shell (and sources .bashrc). bash -c cmd runs cmd.
Put them together:
bash -ic cmd runs cmd in an interactive shell, where cmd can be a bash function/alias defined in your .bashrc
.
find -name \*bar\* | xargs bash -ic gi foo
should do what you want.
Edit: I see you've tagged the question as "tcsh", so the bash-specific solution is not applicable. With tcsh, you dont need the -i
, as it appears to read .tcshrc unless you give -f
.
Try this:
find -name \*bar\* | xargs tcsh -c gi foo
It worked for my basic testing.
回答2:
Turn "gi" into a script instead
eg, in /home/$USER/bin/gi
:
#!/bin/sh
exec /bin/grep -i "$@"
don't forget to mark the file executable.
回答3:
The suggestion here is to avoid xargs and use a "while read" loop instead of xargs:
find -name \*bar\* | while read file; do gi foo "$file"; done
See the accepted answer in the link above for refinements to deal with spaces or newlines in filenames.
回答4:
This is special-character safe:
find . -print0 | xargs -0 bash -ic 'echo gi foo "$@"' --
The -print0
and -0
use \0
or NUL
-terminated strings so you don't get weird things happening when filenames have spaces in them.
bash
sets the first argument after the command string as $0
, so we pass it a dummy argument (--
) so that the first file listed by find
doesn't get consumed by $0
.
回答5:
For tcsh (which does not have functions), you could use:
gi foo `find -name "*bar*"`
For bash/ksh/sh, you can create a function in the shell.
function foobar
{
gi $1 `find . -type f -name "*"$2"*"`
}
foobar foo bar
Remember that using backquotes in the shell is more advantageous than using xargs from multiple perspectives. Place the function in your .bashrc.
回答6:
Using Bash you may also specify the number of args being passed to your alias (or function) like so:
alias myFuncOrAlias='echo' # alias defined in your ~/.bashrc, ~/.profile, ...
echo arg1 arg2 | xargs -n 1 bash -cil 'myFuncOrAlias "$1"' arg0
(should work for tcsh in a similar way)
# alias definition in ~/.tcshrc
echo arg1 arg2 | xargs -n 1 tcsh -cim 'myFuncOrAlias "$1"' arg0 # untested
回答7:
The simplest solution in you case would be to expand your alias inline. But that is valid for csh/tcsh only.
find -name \*bar\* | xargs `alias gi` foo
for bash it will be more tricky, not so handy but still might be useful:
find -name \*bar\* | xargs `alias gi | cut -d "'" -f2` foo
来源:https://stackoverflow.com/questions/979453/how-can-i-use-aliased-commands-with-xargs