Alias jest wewnętrzny dla powłoki, w której jest zdefiniowany. Nie jest widoczny dla innych procesów. To samo dotyczy funkcji powłoki. xargsjest osobną aplikacją, która nie jest powłoką, więc nie ma pojęcia aliasów ani funkcji.
Możesz zmusić xargs do wywoływania powłoki zamiast wywoływania grepbezpośrednio. Jednak samo wywołanie powłoki nie wystarczy, musisz również zdefiniować alias w tej powłoce. Jeśli alias jest zdefiniowany w twoim .bashrcpliku, możesz pobrać ten plik; może to jednak nie działać w przypadku .bashrcwykonywania innych zadań, które nie mają sensu w powłoce nieinteraktywnej.
find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E regex_here "$@"' _
Uważaj na zawiłości cytowania zagnieżdżonego podczas wpisywania wyrażenia regularnego. Możesz uprościć swoje życie, przekazując wyrażenie regularne jako parametr do powłoki.
find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E "$0" "$@"' regex_here
Możesz wykonać wyszukiwanie aliasu jawnie. Wtedy xargszobaczysz grep -n --color=always.
find . -name '*.py' | xargs "${BASH_ALIASES[grep]}" regex_here
W Zsh:
find . -name '*.py' | xargs $aliases[grep] regex_here
Nawiasem mówiąc, zauważ, że find … | xargs … łamie nazwy plików zawierające spacje (między innymi) . Możesz to naprawić, zmieniając rekordy rozdzielane wartościami zerowymi:
find . -name '*.py' -print0 | xargs -0 "${BASH_ALIASES[grep]}" regex_here
lub za pomocą -exec:
find . -name '*.py' -exec "${BASH_ALIASES[grep]}" regex_here {} +
Zamiast dzwonić find, możesz zrobić wszystko całkowicie w powłoce. Wzorzec glob **/rekurencyjnie przechodzi przez katalogi. W bash musisz najpierw uruchomić shopt -s globstarten wzorzec glob.
grep regex_here **/*.py
Ma to kilka ograniczeń:
- Jeśli wiele plików jest zgodnych (lub jeśli mają długie ścieżki), polecenie może się nie powieść, ponieważ przekracza maksymalną długość wiersza polecenia.
- W bash ≤ 4.2 (ale nie w nowszych wersjach, ani w ksh czy zsh),
**/powtarza się w symboliczne linki do katalogów.
Innym podejściem jest stosowanie substytucji procesu, jak sugeruje MariusMatutiae .
grep regex_here <(find . -name '*.py')
Jest to przydatne, gdy **/nie ma zastosowania: dla findwyrażeń złożonych lub w bash ≤4,2, gdy nie chcesz powtarzać się pod symbolicznymi linkami. Zauważ, że powoduje to uszkodzenie nazw plików zawierających spacje; obejściem tego problemu jest ustawienie IFSi wyłączenie globowania , ale zaczyna się ono nieco komplikować :
(IFS=$'\n'; set -f; grep regex_here <(find . -name '*.py') )