An alias is internal to the shell where it is defined. It is not visible to other processes. The same goes for shell functions. xargs
is a separate application, which is not a shell, so doesn't have a concept of aliases or functions.
You can make xargs invoke a shell instead of invoking grep
directly. However just invoking a shell isn't enough, you have to define the alias in that shell as well. If the alias is defined in your .bashrc
, you can source that file; however this may not work your .bashrc
performs other tasks that don't make sense in a non-interactive shell.
find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E regex_here "$@"' _
Beware of the intricacies of nested quoting when typing the regexp. You can simplify your life by passing the regexp as a parameter to the shell.
find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E "$0" "$@"' regex_here
You can perform the alias lookup explicitly. Then xargs
will see grep -n --color=always
.
find . -name '*.py' | xargs "${BASH_ALIASES[grep]}" regex_here
In zsh:
find . -name '*.py' | xargs $aliases[grep] regex_here
By the way, note that find … | xargs …
breaks on filenames containing spaces (among others). You can fix this by changing to null-delimited records:
find . -name '*.py' -print0 | xargs -0 "${BASH_ALIASES[grep]}" regex_here
or by using -exec
:
find . -name '*.py' -exec "${BASH_ALIASES[grep]}" regex_here {} +
Instead of calling find
, you can do everything entirely inside the shell. The glob pattern **/
traverses directories recursively. In bash, you need to run shopt -s globstar
to enable this glob pattern first.
grep regex_here **/*.py
This has a few limitations:
- If a lot of files match (or if they have long paths), the command may fail because it exceeds the maximum command line length.
- In bash ≤4.2 (but not in more recent versions, nor in ksh or zsh),
**/
recurses into symbolic links to directories.
Another approach is to use process substitution, as suggested by MariusMatutiae.
grep regex_here <(find . -name '*.py')
This is useful when **/
isn't applicable: for complex find
expressions, or in bash ≤4.2 when you don't want to recurse under symbolic links. Note that this breaks on file names containing spaces; a workaround is to set IFS
and disable globbing, but it's starting to get a bit complex:
(IFS=$'\n'; set -f; grep regex_here <(find . -name '*.py') )
xargs
command. What I'm trying to find out is if there's a way that I can directly call my alias fromxargs
. – MattDMo Jul 08 '14 at 16:51