Форум русскоязычного сообщества Ubuntu


Следите за новостями русскоязычного сообщества Ubuntu в Twitter-ленте @ubuntu_ru_loco

Автор Тема: Приведение к нижнему регистру файлов вместе с подкаталогами.  (Прочитано 2615 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн pseex

  • Автор темы
  • Новичок
  • *
  • Сообщений: 21
    • Просмотр профиля
Давно искал ответ как это сделать, нашел несколько советов, но сам сделал так в гном-терминале:
find ./ -name "*" -exec rename 'y/A-Z/a-z/' {} \;
Вроде бы и работает, но иногда ругается, например так "find: `./Bin': Нет такого файла или каталога", хотя он есть и при повторном использовании команды - проходит без ошибок, т.о., если ругнулась - запускаю до тех пор, пока не перестает сыпать ошибки...Вот только почему ругается - не понятно.

Оффлайн avi9526

  • Активист
  • *
  • Сообщений: 618
  • ахтыжъёшкинкот
    • Просмотр профиля
    • Блог av9526
ИМХО (я вообще консольные команды не шарю :P)
Утилита «find» обнаружила каталог «Bin» запустила команду переименования, а потом пытается просканировать содержимое, но каталога «Bin» уже нет, есть «bin», но «find» не знает об этом. Как-то так, я думаю…
Надо использовать опцию утилиты «find» под названием «depth» (man find) - содержимое каталога обрабатывается до него. Но и это не все, теперь проблема будет с «rename», оно будет пытаться переименовать, например, «./Hello/Privet» в «./hello/privet» и естественно, не сможет, поскольку «hello» еще нет.
Надо поменять шаблон вызова «rename». Вот здесь здесь собственно написано. Короче говоря, команда
find ./ -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;переименовала мне тестовые папки
.
├── Hello
│   └── Privet
└── Wtf
    └── doH
без единого матюка, хотя с шаблоном 'y/A-Z/a-z/' не хотела…
« Последнее редактирование: 15 Ноября 2012, 14:25:43 от avi9526 »
Ubuntu 14.10

Оффлайн Artif

  • Участник
  • *
  • Сообщений: 207
    • Просмотр профиля
А если два каталога ./Bin и ./bin?

По ссылке люди много мудрят с регулярными выражениями. Чревато ошибками. Там же - надо читать документацию: что произойдёт при неожиданном отключении электричества, что будет если после переиначивания имени обнаружился уже существующий файл с тем именем. Надо. Читать. :)

Я бы так сделал - последовательный обход всех уровней каталогов, от малых глубин к большим, пока не случится "ничего не найдено":
#!/bin/bash

declare -r directoryTheTop="${1:-.}"
declare -r tmpFile="$( mktemp )"

trap "rm -f '${tmpFile}'" INT TERM EXIT

echo "Starting at \"${directoryTheTop}\". $( date )" >&2
depthValue=0
while :
do
    echo "====> Going at depth ${depthValue}." >&2
    while read foundFileOrDir
    do
        if [ -z "${foundFileOrDir}" ]
        then
            echo "Job done. $( date )" >&2
            exit
        fi
        dirCurrentlyIsProcessed="$( dirname "${foundFileOrDir}" )"
        fileNameSource="$( basename "${foundFileOrDir}" )"
        fileNameDestinationAndLowercase="${fileNameSource,,*}"

        if [ -e "${fileNameDestinationAndLowercase}" ] \
            && [ "${fileNameSource}" != "${fileNameDestinationAndLowercase}" ]
        then
            echo "$0 at $LINENO that: already exist '${dirCurrentlyIsProcessed}/${fileNameDestinationAndLowercase}', will skip it." >&2
            #echo "$0 at $LINENO that: already exist '${dirCurrentlyIsProcessed}/${fileNameDestinationAndLowercase}', will skip it." > "${tmpFile}"
        elif [ "${fileNameSource}" == "${fileNameDestinationAndLowercase}" ]
        then
            true
        else
            echo "mv --force \"${dirCurrentlyIsProcessed}/${fileNameSource}\" \"${dirCurrentlyIsProcessed}/${fileNameDestinationAndLowercase}\""
        fi
    done <<< "$( find "${directoryTheTop}" -mindepth ${depthValue} -maxdepth ${depthValue} )"

    echo "----> Leaving depth ${depthValue}." >&2
    ((depthValue++))
    #sleep 2
done

Этот код сохранить в файлик /usr/bin/meAndRename
Сделать:
chown ${USER}:${USER} "/usr/bin/meAndRename"
chmod 755 "/usr/bin/meAndRename"
Правильнее ${USER} заменить на root. Или не класть скрипт в каталог типа '/usr/bin/', который прописан в PATH.

Запускать либо без параметров в каталоге где нужно всё переименовать. Или запускать:
meAndRename "имя/каталога/который/надо/обработать"
Текущий код ничего не делает. Он только пишет на экран предполагаемые команды. Можно сделать:
meAndRename "имя/каталога/который/надо/обработать" 1>/tmp/rename-commands
Изучить "/tmp/rename-commands", если всё нормально - запустить /tmp/rename-commands:
bash /tmp/rename-commands
Дьявол в деталях: если было использовано универсальное имя текущего каталога '.', то /tmp/rename-commands можно запускать только в том каталоге, для которого он был сгенерирован.

Активируется скрипт заменой
echo "mv --force \"${dirCurrentlyIsProcessed}/${fileNameSource}\" \"${dirCurrentlyIsProcessed}/${fileNameDestinationAndLowercase}\""
на
mv --force "${dirCurrentlyIsProcessed}/${fileNameSource}" "${dirCurrentlyIsProcessed}/${fileNameDestinationAndLowercase}"


Предусмотрена фича сброса в лог файл, но деактивирована.

P.S. Я особо не отлаживал. Осторожно.
« Последнее редактирование: 16 Ноября 2012, 12:17:03 от Artif »

Оффлайн pseex

  • Автор темы
  • Новичок
  • *
  • Сообщений: 21
    • Просмотр профиля
Какой же я ещё маленький  :D

Оффлайн igor822605

  • Участник
  • *
  • Сообщений: 229
    • Просмотр профиля
Есть много каталогов с подкаталогами содержащие в имени файлов с   вот такими символами, как можно их заменить?


Оффлайн ArcFi

  • Старожил
  • *
  • Сообщений: 15189
    • Просмотр профиля
    • aetera.net
igor822605, убрать левые символы из имён файлов можно так:
Код: (bash) [Выделить]
find /dir -exec prename 's/[^0-9a-zA-Zа-яА-Я\ \-\_\=\+\,\.\;\:\<\>\/\|\!\@\#\$\%\^\&\(\)\[\]\{\}]//' {} \;
Однако, для файлов с одинаковыми конечными именами надо придумывать дополнительную обработку, либо переименовывать/переносить вручную.
« Последнее редактирование: 15 Декабря 2012, 17:58:45 от arcfi »

Оффлайн igor822605

  • Участник
  • *
  • Сообщений: 229
    • Просмотр профиля
 Спасибо. У меня не получилось скопировать в терминал значки в квадрате с цифрами, при копировании єтих значков команда мутирует в непонятно что.

Оффлайн ArcFi

  • Старожил
  • *
  • Сообщений: 15189
    • Просмотр профиля
    • aetera.net
У меня не получилось скопировать в терминал значки в квадрате с цифрами, при копировании єтих значков команда мутирует в непонятно что.
Можно сохранить в файл, сделать его исполняемым и запускать как скрипт.

Оффлайн igor822605

  • Участник
  • *
  • Сообщений: 229
    • Просмотр профиля
Попробуйте, пожалуйста с єтим файлом.

Оффлайн ArcFi

  • Старожил
  • *
  • Сообщений: 15189
    • Просмотр профиля
    • aetera.net
Пришлось модифицировать регэксп, чтобы корректно обрабатывались русские буквы.

Вот, работает:
Код: (bash) [Выделить]
$ ls Загрузки/
?a6a-a1a5a0aDCB1aaLa.jpg

$ find Загрузки/ -exec prename 's/[^0-9a-zA-ZАаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬьЭэЮюЯя\ \-\_\=\+\,\.\;\:\<\>\/\|\!\@\#\$\%\^\&\(\)\[\]\{\}]//' {} \;

$ ls Загрузки/
a6a-a1a5a0aDCB1aaLa.jpg

Оффлайн igor822605

  • Участник
  • *
  • Сообщений: 229
    • Просмотр профиля
Странно, у меня єтот файл начинается не с знака вопроса.

Оффлайн ArcFi

  • Старожил
  • *
  • Сообщений: 15189
    • Просмотр профиля
    • aetera.net
Странно, у меня єтот файл начинается не с знака вопроса.
Нет там знака вопроса, там символ с кодом 'x1F'.
Просто в эмуляторе терминала левые символы отображаются вопросами.

Оффлайн igor822605

  • Участник
  • *
  • Сообщений: 229
    • Просмотр профиля
Огромное спасибо.
Цитировать
�����
а как обозначить єти символы?

Оффлайн victor00000

  • Старожил
  • *
  • Сообщений: 15568
  • Глухонемой (Deaf)
    • Просмотр профиля
ls | iconv -t WINDOWS-1251 -f UTF-8
Wars ~.o

 

Страница сгенерирована за 0.021 секунд. Запросов: 21.