Массовое переименование файлов с верблюжьим регистром для включения пробелов

Реализация случая, который вы специально сформулировали в своем вопросе, будет сложной задачей и потребует некоторых сценариев bash, которые я не рекомендую для такой простой задачи.

Но очень похожая вещь может быть достигнута с помощью параметра AddKyesToAgent в ssh_config , который в основном добавляет ключи к ssh-agent , когда он используется для первый раз. Эта опция доступна, начиная с OpenSSH 7.2 .

5
23.12.2016, 23:34
3 ответа

Проблема в том, что суб-оболочка $ (...) в вашей команде оценивается во время выполнения команды , и не оценивается 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 . (Но это уже существующее ограничение в вашей собственной попытке, поэтому я надеюсь, что это приемлемо.)

5
27.01.2020, 20:37

Ваша команда 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 пройдёт по нему.

2
27.01.2020, 20:37

Если вы предпочитаете использовать GNU Parallel, решение следующее:

find . -name "*[a-z][A-Z]*" -type f | parallel mv -v {} '{= s:([a-z])([A-Z])(?!.*/):$1 $2:g =}'
1
27.01.2020, 20:37

Теги

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