LINUX.ORG.RU

Смена кодировки имен файлов

 , ,


0

3

Здравствуйте. Как перекодировать имена файлов и каталогов вида #U0440#U0438#U0441#U0443#U043d#U043e#U043a-1.png и подобного? Их очень много и это по ходу когда-то было в UTF-8 и теперь с ними что-то случилось. Прошу помощи. Пробовал convmv, но это кажется не то что нужно.


Ответ на: комментарий от zz84

Скрипт напишу, но приведете пример команды как конвертировать хотя бы один файл?

$ echo -e $(echo '#U0440#U0438#U0441#U0443#U043d#U043e#U043a-1.png' | tr '#' '\\')
рисунок-1.png

Но учти, что этот код небезопасен. Например, если в каком-то имени окажутся закодированные юникодом ../../../../../etc/passwd то после запуска такого скрипта от рута файл /etc/passwd будет перезаписан, так что в реальном скрипте нужно ввести дополнительные проверки. Ну и ещё нет гарантий, что подобная команда корректно отработает для всех имён.

Считай что это просто proof of concept

Xenius ★★★★★ ()
Последнее исправление: Xenius (всего исправлений: 2 )
Ответ на: комментарий от Xenius

Кроме того, заменятся не только #Uxxxx но и другие последовательности, что может быть нежелательным.

Но тут нужно проанализировать всё дерево, встречаются ли там другие спецсимволы. Есть ли там # в другом контексте и тд.

Xenius ★★★★★ ()
Последнее исправление: Xenius (всего исправлений: 1 )

это по ходу когда-то было в UTF-8

что было, сказать теперь вряд ли возможно, но то, что есть — это UCS2 или UTF-16, причем первые 2 цифры — 04 — старший байт.

bormant ★★★★★ ()
Ответ на: комментарий от Xenius

Спасибо большое! Попробовал вот такой скрипт:

for file in `find ./ -type f -name "*"`
do
MSG=$(echo -e $(echo ${file} | tr '#' '\\'))
echo ${MSG}
done

и там где есть пробелы, выдаёт не одной строкой:

./images/ABB/Выключатели
нагрузки
в
боксах/PaxHeader/2CMC300007F0026_720.jpg
./images/ABB/Выключатели
нагрузки
в
боксах/PaxHeader/2CMC300007F0025_720.jpg
./images/ABB/Выключатели
нагрузки
в
боксах/PaxHeader/S00507A_195.jpg
./images/ABB/Выключатели
нагрузки
в
боксах/PaxHeader/OTC_kansi_FL_720.jpg

Как это можно сделать чтобы одной строкой выводило а не переносило на следующую?

zz84 ()
Ответ на: комментарий от zz84

for file in `find ./ -type f -name «*»`

Кто же так делает-то? Это одна из типичных ошибок.

Вообще на этом сайте описано множество типичных ошибок пишущих скрипты.

Кроме того -name «*» вообще излишен.

Xenius ★★★★★ ()
Последнее исправление: Xenius (всего исправлений: 1 )
Ответ на: комментарий от zz84

Спасибо, но как всё-же сделать чтобы не переносило на новую строку?

Не использовать for для итерации. У find есть параметр -exec

Как бы сделали Вы? :-)

Я бы писал на Tcl, и так чтобы заменялись только куски с #Uxxxx, и после замены проводилась проверка на корректность имени.

Xenius ★★★★★ ()
Последнее исправление: Xenius (всего исправлений: 4 )

Всем спасибо! Решилось как-то вот так: Правда остались дубликаты в иероглифах, но их вручную поудалял...

#!/bin/bash

find ./uploads -print0 | while read -d $'\0' FILE; do

RES=$(echo -e $(echo ${FILE} | tr '#' '\\'))
mv -f  "${FILE}" "${RES}"

done
zz84 ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.