Уменьшение всех каталогов под каталогом

Я хочу записать каждое имя каталогов под каталогом. С какими командами я могу это сделать?

  • mv файлы на другой путь, который создается с помощью замены регулярных выражений
  • переименовывать случайные файлы на USB-устройстве
  • Как перемещать все файлы и папки с помощью команды mv
  • Селективный рекурсивный ход?
  • Разделить имена файлов и переименовать
  • Рекурсивно переименовывать файлы и каталоги
  • Linux Переименовать файл Начиная с «-»
  • Пакетное копирование / перемещение файлов в unix?
  • 3 Solutions collect form web for “Уменьшение всех каталогов под каталогом”

    Все каталоги на одном уровне или рекурсивно?

    Zsh

    На одном уровне:

    autoload zmv zmv -oi -Q 'root/(*)(/)' 'root/${1:l}' 

    Рекурсивный:

     zmv -oi -Q 'root/(**/)(*)(/)' 'root/$1${2:l}' 

    Объяснения: zmv переименовывает файлы, соответствующие шаблону в соответствии с данным текстом замены. -oi передает параметр -i для каждой команды mv под капотом (см. ниже). В заменяющем тексте $1 , $2 и т. Д. Являются последовательными скобками в шаблоне. ** означает все (под) * каталоги, рекурсивно. Финал (/) не является группой в скобках, но квалификатором glob означает соответствие только каталогов. ${2:l} преобразует $2 в нижний регистр.

    портативный

    На одном уровне:

     for x in root/*/; do mv -i "$x" "$(printf %s "$x" | tr '[:upper:]' '[:lower:]')"; done 

    Финал / ограничивает соответствие каталогов, а mv -i запрашивает подтверждение при столкновении. Удалите -i чтобы перезаписать в случае столкновения, и используйте yes n | for … yes n | for … чтобы не было предложено и не выполнялось какое-либо переименование, которое могло бы столкнуться.

    Рекурсивный:

     find root/* -depth -type d -exec sh -c ' t=${0%/*}/$(printf %s "${0##*/}" | tr "[:upper:]" "[:lower:]"); [ "$t" = "$0" ] || mv -i "$0" "$t" ' {} \; 

    Использование -depth гарантирует, что глубоко вложенные каталоги обрабатываются перед своими предками. Обработка имен зависит от наличия / ; если вы хотите вызвать ./* в текущем каталоге, используйте ./* (адаптация сценария оболочки для ./* с помощью . или * остается в качестве упражнения для читателя).

    Перл переименовать

    Здесь я использую скрипт переименования Perl, который Debian и Ubuntu отправляют как /usr/bin/prename (обычно доступны как rename ). На одном уровне:

     rename 's!/([^/]*/?)$!\L/$1!' root/*/ 

    Рекурсивно, с bash ≥4 или zsh:

     shopt -s globstar # only in bash rename 's!/([^/]*/?)$!\L/$1!' root/**/*/ 

    Рекурсивно, портативно:

     find root -depth -type d -exec rename -n 's!/([^/]*/?)$!\L/$1!' {} + 

    Не существует одной команды, которая сделает это, но вы можете сделать что-то вроде этого:

     for fd in */; do #get lower case version fd_lower=$(printf %s "$fd" | tr AZ az) #if it wasn't already lowercase, move it. [ "$fd" != "$fd_lower" ] && mv "$fd" "$fd_lower" done 

    Если вам нужно, чтобы он был надежным, вы должны учитывать, когда есть два каталога, которые отличаются только в случае.

    Как однострочный:

     for fd in */; do fd_lower=$(printf %s "$fd" | tr AZ az) && [ "$fd" != "$fd_lower" ] && mv "$fd" "$fd_lower"; done 

    Я воспринял это как вызов с одним лайнером 🙂 Сначала создайте тестовый пример:

     $ for d in foo Bar eVe; do mkdir -p dcthis/$d; touch dcthis/a${d}.txt; done $ ls dcthis/ Bar aBar.txt aeVe.txt afoo.txt eVe foo 

    Я использую find чтобы определить каталоги с прописными буквами, а затем опустить их через sh -c 'mv {} echo {} | tr [:upper:] [:lower:] ' sh -c 'mv {} echo {} | tr [:upper:] [:lower:] ' . Угадай, что использовать sh -c немного хак-иш, но моя голова всегда взрывается, когда я пытаюсь избежать непосредственного find вещей.

     $ (cd dcthis && find . -maxdepth 1 -type d -path '*[AZ]*' -exec sh -c 'mv {} `echo {} | tr [:upper:] [:lower:]`' \;) $ ls dcthis/ aBar.txt aeVe.txt afoo.txt bar eve foo 

    Будьте осторожны: это решение не проверяет, приводит ли перепад в столкновение!

    Linux и Unix - лучшая ОС в мире.