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. xargs
jest 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 grep
bezpoś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 .bashrc
pliku, możesz pobrać ten plik; może to jednak nie działać w przypadku .bashrc
wykonywania 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 xargs
zobaczysz 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 globstar
ten 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 find
wyraż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 IFS
i wyłączenie globowania , ale zaczyna się ono nieco komplikować :
(IFS=$'\n'; set -f; grep regex_here <(find . -name '*.py') )