Реализация случая, который вы специально сформулировали в своем вопросе, будет сложной задачей и потребует некоторых сценариев bash, которые я не рекомендую для такой простой задачи.
Но очень похожая вещь может быть достигнута с помощью параметра AddKyesToAgent
в ssh_config
, который в основном добавляет ключи к ssh-agent
, когда он используется для первый раз. Эта опция доступна, начиная с OpenSSH 7.2 .
Проблема в том, что суб-оболочка $ (...)
в вашей команде оценивается во время выполнения команды , и не оценивается xargs
для каждого файла.
Вы можете использовать find
-exec
вместо того, чтобы оценивать команды для каждого файла в sh
, а также замените кавычки соответствующим образом:
find . -name "*[a-z][A-Z]*" -type f -exec sh -c 'echo mv -v "{}" "$(echo "{}" | sed -E "s/([a-z])([A-Z])/\1 \2/g")"' \;
Если результат выглядит хорошо, отбросьте echo
в echo mv
.
Обратите внимание, что из-за echo | sed
, это не будет работать с именами файлов со встроенным \ n
. (Но это уже существующее ограничение в вашей собственной попытке, поэтому я надеюсь, что это приемлемо.)
Ваша команда sed
принимает входные данные из канала. Он конкурирует с xargs
, поэтому каждая из двух команд получит часть данных, записанных с помощью find
(каждый байт достается только одному считывающему устройству), и кто что получит, непредсказуемо.
Вам нужно будет передать каждое имя файла в sed
, что означает, что вам понадобится промежуточная оболочка для настройки канала.
find . -name "*[a-z][A-Z]*" -print0 | xargs -0 -I {} sh -c 'mv "$0" "$(echo "$0" | sed -E '\''s/([a-z])([A-Z])/\1 \2/g'\'')"' {}
Вам не нужны xargs
, в большинстве случаев это бесполезно. find
может вызывать программу напрямую.
find . -name "*[a-z][A-Z]*" -exec sh -c 'mv "$0" "$(echo "$0" | sed -E '\''s/([a-z])([A-Z])/\1 \2/g'\'')"' {} \;
В качестве альтернативы установите любую из реализаций Perl переименования
, например File :: Rename
или вариант из Unicode :: Tussle
.
cpan File::Rename
find -depth . -exec rename 's!([a-z])([A-Z])(?!.*/)!$1 $2!g' {} +
Бит (?!. * /)
предотвращает запуск замены в именах каталогов, если они содержат верблюжий регистр. Передача -depth
в find
гарантирует, что если каталог будет переименован, это произойдет после того, как find
пройдёт по нему.
Если вы предпочитаете использовать GNU Parallel, решение следующее:
find . -name "*[a-z][A-Z]*" -type f | parallel mv -v {} '{= s:([a-z])([A-Z])(?!.*/):$1 $2:g =}'