xargs не распознает псевдонимы bash
-
21-08-2019 - |
Вопрос
Я пытаюсь выполнить следующую команду:
find . -iname '.#*' -print0 | xargs -0 -L 1 foobar
где "foobar" - это псевдоним или функция, определенная в моем файле .bashrc (в моем случае это функция, которая принимает один параметр).Очевидно, xargs не распознает их как вещи, которые он может запускать.Есть ли умный способ исправить это?
Решение
Поскольку только ваша интерактивная оболочка знает об псевдонимах, почему бы просто не запустить псевдоним без разветвления через xargs
?
find . -iname '.#*' -print0 | while read -r -d '' i; do foobar "$i"; done
Если вы уверены, что в ваших именах файлов нет новых строк (черт возьми, с чего бы это?), вы можете упростить это до
find . -iname '.#*' -print | while read -r i; do foobar "$i"; done
или даже просто find -iname '.#*' | ...
, поскольку каталог по умолчанию является .
и действие по умолчанию таково -print
.
Еще одна альтернатива:
IFS=$'\n'; for i in `find -iname '.#*'`; do foobar "$i"; done
сообщаю Bash, что слова разбиваются только на новые строки (по умолчанию: IFS=$' \t\n'
).Однако вам следует быть с этим поосторожнее;некоторые скрипты плохо справляются с измененным $IFS
.
Другие советы
Используя Bash, вы также можете указать количество аргументов, передаваемых вашему псевдониму (или функции), следующим образом:
alias myFuncOrAlias='echo' # alias defined in your ~/.bashrc, ~/.profile, ...
echo arg1 arg2 | xargs -n 1 bash -cil 'myFuncOrAlias "$1"' arg0
echo arg1 arg2 | xargs bash -cil 'myFuncOrAlias "$@"' arg0
Это не работает, потому что xargs
ожидает, что сможет exec
тот самый программа задается в качестве его параметра.
С тех пор как foobar
в вашем случае это просто bash
псевдоним или функция, в которых нет программы для выполнения.
Хотя это предполагает начало bash
для каждого файла, возвращенного find
, вы могли бы написать небольшой сценарий оболочки таким образом:
#!/bin/bash
. $(HOME)/.bashrc
func $*
а затем передайте имя этого скрипта в качестве параметра xargs
Обычно я использую find следующим образом:
find . -iname '' -exec cmd '{}' \;
'{}' будет заменено именем файла, и \;это необходимо для завершения цепочки выполнения.Однако, если это не работает с вашей функцией, вам может потребоваться запустить ее через bash:
find .. |sed -e "s/.*/cmd '&'/"|bash
Find печатает каждый файл в строке, sed просто добавляет к нему префикс вашей команды, а затем передает его в bash для выполнения.Сначала пропустите |bash, чтобы посмотреть, что произойдет.
попробуй
find . -iname '.#*' -print0 | xargs -0 -L 1 $(foobar)