Intereting Posts
Как я могу исправить ошибки в KDE Start Menu / Launcher? Как использовать Awk для форматирования чисел с разделителем тысяч Терминал говорит, что команда не найдена при запуске Почему IP-адрес для Linux Bridge, который является виртуальным устройством уровня 2? Запуск процесса после загрузки Linux Mint (Cinnamon, Muffin) установил сочетание клавиш, где один из клавиш – это мышь Как раскрасить текст в emacs? Запуск существующего сеанса tmux при входе в SSH или создание, если не существует Есть ли способ подсчитать количество совпадений в Vim, используя: g? Как исправить прерывистые ошибки «Нет места на устройстве» во время mv, когда у устройства достаточно места? Ubuntu 16.04 Скрипты в файле /etc/profile.d Как подключиться к серверу ssh и запросить программные подсказки? Зеркало или кеширование репозитория Debian Изменение цвета PS1 при подключении к другому хосту через SSH В Solaris 10 и 11 все еще используется распределение slab для их распределителя памяти ядра

Применение функции bash для каждого файла в подпапке рекурсивно

Я пытаюсь написать сценарий, который будет применять функцию bash для каждого файла в каталоге рекурсивно. Например, если в tests каталога были все мои файлы и подкаталоги, сценарий

 find tests -type f -print0 | xargs -0 echo 

Работает отлично. Теперь я хочу использовать функцию bash, а не просто эхо, поэтому я придумал что-то вроде этого:

 function fun() { echo $1 } export -f fun find tests -type f -print0 | xargs -0 bash -c 'fun "$@"' 

Однако это выводит только один файл в тестах, где перед ним выводятся все файлы. Я бы ожидал, что эти два будут работать одинаково?

Есть два способа решить эту проблему: вы можете либо сказать xargs запустить команду только с одним аргументом, используя -n1 или loop для всех аргументов внутри вашей функции fun :

 function fun() { echo $1 } export -f fun find tests -type f -print0 | xargs -n1 -0 bash -c 'fun "$@"' -- 

или

 function fun() { while [ -n "$1" ]; do echo $1; shift; done } export -f fun find tests -type f -print0 | xargs -0 bash -c 'fun "$@"' -- 

Используйте сценарий оболочки.

Чтобы процитировать этот отличный ответ :

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

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

 #!/bin/bash # I'm a script named "fun"! :) printf '%s\n' "$@" 

Затем вы просто помещаете fun скрипт где-то в своем PATH (возможно, в ~/bin ), убедитесь, что он выполним, и вы можете запустить:

 find tests -type f -exec fun {} + 

Если вы используете GNU Parallel, это выглядит так:

 function fun() { echo "$@" } export -f fun find tests -type f -print0 | parallel -0 -Xj1 fun