Имейте псевдоним использования xargs вместо двоичного файла

То, что Вы хотите, является eCryptfs. См. этот ответ, который я дал подобному вопросу на StackOverflow только что.


Править:

Я не думаю, что Вы должны downvote совершенно хорошие ответы просто, потому что Вы не были достаточно явными в своем вопросе - только тег? Так или иначе... GnuPG / PGP не может сделать то, что Вы хотите. Сравнение выезда программного обеспечения шифрования диска на Википедию. Похож на Ваш единственный выбор, "svnd / vnconfig".

13
09.07.2014, 16:56
5 ответов

Псевдоним является внутренним по отношению к оболочке, в которой он определен. Это не видно другим процессам. То же самое и с функциями оболочки. xargs - это отдельное приложение, которое не является оболочкой, поэтому не имеет концепции псевдонимов или функций.

Вы можете заставить xargs вызывать оболочку вместо прямого вызова grep . Однако простого вызова оболочки недостаточно, вы также должны определить псевдоним в этой оболочке. Если псевдоним определен в вашем .bashrc , вы можете использовать этот файл как источник; однако это может не сработать. Ваш .bashrc выполняет другие задачи, которые не имеют смысла в неинтерактивной оболочке.

find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E regex_here "$@"' _

Остерегайтесь тонкостей вложенного цитирования при вводе регулярного выражения. Вы можете упростить себе жизнь, передав регулярное выражение в качестве параметра в оболочку.

find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E "$0" "$@"' regex_here

Вы можете выполнить поиск псевдонима явно. Тогда xargs увидит grep -n --color = always .

find . -name '*.py' | xargs "${BASH_ALIASES[grep]}" regex_here

В zsh:

find . -name '*.py' | xargs $aliases[grep] regex_here

Кстати, обратите внимание, что find… | xargs… разбивает имена файлов, содержащие пробелы (среди прочего) . Вы можете исправить это, изменив записи с разделителями на нуль:

find . -name '*.py' -print0 | xargs -0 "${BASH_ALIASES[grep]}" regex_here

или используя -exec :

find . -name '*.py' -exec "${BASH_ALIASES[grep]}" regex_here {} +

Вместо вызова find вы можете делать все полностью внутри оболочки. Шаблон glob ** / рекурсивно просматривает каталоги. В bash вам нужно запустить shopt -s globstar , чтобы сначала включить этот шаблон глобуса.

grep regex_here **/*.py

Это имеет несколько ограничений:

  • Если много файлов совпадают (или если у них длинные пути), команда может завершиться ошибкой, потому что она превышает максимальную длину командной строки.
  • В bash ≤4.2 (но не в более поздних версиях, ни в ksh, ни в zsh) ** / рекурсивно превращается в символические ссылки на каталоги.

Другой подход состоит в том, чтобы использовать замену процесса, как это было предложено MariusMatutiae .

grep regex_here <(find . -name '*.py')

Это полезно, когда ** / неприменимо: для сложных выражений find или в bash ≤4.2, когда вы не хотите выполнять рекурсию по символическим ссылкам. Обратите внимание, что это нарушает имена файлов, содержащие пробелы; обходной путь - установить IFS и отключить подстановку , но это начинает становиться немного сложнее:

(IFS=$'\n'; set -f; grep regex_here <(find . -name '*.py') )
10
27.01.2020, 19:52

Пожалуйста, воспримите это как демонстрацию другого подхода, который я не могу найти в соответствующем SO question:

Вы можете написать функцию обёртки для xargs, которая проверяет, является ли первый аргумент псевдонимом, и если да, то разверните его соответствующим образом.

Вот код, который делает именно это, но, к сожалению, требует оболочки Z и, следовательно, не запускается 1:1 с bash (и, честно говоря, я не привык к bash достаточно, чтобы портировать его) :

xargs () {
        local expandalias
        if [[ $(which $1) =~ "alias" ]]; then
                expandalias=$(builtin alias $1) 
                expandalias="${${(s.'.)expandalias}[2]}"
        else
                expandalias=$1
        fi
        command xargs ${(z)expandalias} "${(z)@[2,-1]}"
}

Доказательство того, что он работает:

zsh% alias grep="grep -n"´                          # include line number of match
zsh% find foo -name "*.p*" | xargs grep -E test
foo/bar.p0:151:#data=test
foo/bar.p1:122:#data=test                           # line numbers included
zsh% unalias grep
zsh% find foo -name "*.p*" | xargs grep -E test
foo/bar.p0:#data=test
foo/bar.p1:#data=test                               # line numbers not included
zsh% 
2
27.01.2020, 19:52
[

]grep будет считывать набор опций по умолчанию из переменной окружения GREP_OPTIONS. Если вы поместите[

] [
 export GREP_OPTIONS='--line-number --color=always'
] [

]в .bashrc, то переменная будет передана в подоболочки и вы получите ожидаемые результаты.[

].
0
27.01.2020, 19:52

Более простым и элегантным решением является использование замены процесса :

grep -E 'regex_here' <( find . -name '*.py')

Он не создает новую оболочку, как это делает труба, что означает, что вы все еще находитесь в своей оригинальной оболочке, в которой определен псевдоним, и результат будет именно таким, каким вы хотите, чтобы он был.

Просто будьте осторожны, чтобы не оставить места между перенаправлением и скобками, иначе bash выдаст ошибку. Насколько мне известно, подстановка процесса поддерживается Bash, Zsh, Ksh{88,93}, но не pdksh (мне сказали, что это должно быть еще не ).

1
27.01.2020, 19:52

Используйте псевдоним xargs = 'xargs'

alias: alias [-p] [name[=value] ... ]
(snip)
A trailing space in VALUE causes the next word to be checked for
alias substitution when the alias is expanded.
11
27.01.2020, 19:52

Теги

Похожие вопросы