У меня есть несколько каталогов и подкаталогов, которые содержат файлы со специальными символами, например, этот файл:
robbie@phil:~$ ls test�sktest.txt
test?sktest.txt
Find обнаруживает escape-последовательность:
robbie@phil:~$ find test�sktest.txt -ls
424512 4000 -rwxr--r-x 1 robbie robbie 4091743 Jan 26 00:34 test\323sktest.txt
Единственная причина, по которой я могу даже ввести их имена в консоли, заключается в завершении табуляции. Это также означает, что я могу переименовать их вручную (и удалить специальный символ).
Я установил LC_ALL в UTF-8, что, похоже, не помогает (также не в новой оболочке):
robbie@phil:~$ echo $LC_ALL
en_US.UTF-8
Я подключаюсь к машине, используя ssh с моего mac. Это установка Ubuntu:
robbie@phil:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=7.10
DISTRIB_CODENAME=gutsy
DISTRIB_DESCRIPTION="Ubuntu 7.10"
Shell это Bash, TERM установлен в цвет xterm.
Эти файлы были там в течение достаточно долгого времени, и они не были созданы с использованием этой установки Ubuntu. Так что я не знаю, какими были системные настройки кодирования.
Я пробовал что-то вроде:
find . -type f -ls | sed 's/[^a-zA-Z0-9]//g'
Но я не могу найти решение, которое делает все, что я хочу:
- Определите все файлы, которые имеют не отображаемые символы (приведенное выше игнорирует слишком много)
- Для всех этих файлов в дереве каталогов (рекурсивно) выполните mv oldname newname
- По желанию, возможность транслитерации специальных символов, таких как ä, в (не обязательно, но было бы здорово)
ИЛИ
- Правильно отображать все эти файлы (и без ошибок в приложениях при попытке их открыть)
У меня есть кусочки, такие как перебирать все файлы и перемещать их, но идентификация файлов и их правильное форматирование для команды mv, кажется, трудная часть.
Любая дополнительная информация о том, почему они не отображаются правильно, или как «угадать» правильную кодировку, также приветствуется. (Я пробовал convmv, но, похоже, он не выполняет именно то, что мне нужно: http://j3e.de/linux/convmv/ )
Ответы:
Я думаю, вы видите этот
�
недопустимый символ, потому что имя содержит последовательность байтов, которая не является допустимой UTF-8. Имена файлов в типичных файловых системах Unix (включая вашу) являются байтовыми строками, и приложения должны решать, какую кодировку использовать. В настоящее время существует тенденция использовать UTF-8, но он не универсален, особенно в локалях, которые никогда не могли жить с простым ASCII и использовали другие кодировки еще до того, как UTF-8 даже существовал.Попробуйте
LC_CTYPE=en_US.iso88591 ls
посмотреть, имеет ли имя файла смысл в ISO-8859-1 (латиница-1). Если это не так, попробуйте другие локали. Обратите внимание, чтоLC_CTYPE
здесь важна только настройка локали.В локали UTF-8 следующая команда покажет вам все файлы, чье имя не является допустимым UTF-8:
Вы можете проверить, имеют ли они смысл в другой локали с помощью recode или iconv :
Как только вы определили, что группа имен файлов находится в определенной кодировке (например, latin1), один из способов переименовать их
Здесь используется команда perl rename, доступная в Debian и Ubuntu. Вы можете передать его,
-n
чтобы показать, что он будет делать, не переименовывая файлы.источник
grep [^[:print:]]
в виду поиск непечатных символов. Но я только что протестировал GNU grep, и недопустимые последовательности UTF-8 не обнаруживаются[^[:print:]]
(что имеет смысл, поскольку они не непечатаемые символы, они вообще не символы). Я отредактировал свой пост более длинным способом подрезания строк с недопустимыми последовательностями utf8. Обратите внимание, что я также зафиксировал направлениеrecode
иiconv
примеры.Я знаю, что это старый вопрос, но я всю ночь искал подобное решение. Я нашел несколько полезных советов, но они не делали именно то, что мне нужно, поэтому мне пришлось смешивать и сочетать несколько, чтобы получить правильный результат, который я искал
просто удалить специальные символы и заменить их точкой (.)
чтобы использовать в cronjob я сделал следующее, чтобы бегать каждую минуту
Я надеюсь, что кто-то найдет это полезным, поскольку это сделало мой день :)
источник
`…`
на ...$(…)
увидеть это , это и это . (2) Вы всегда должны цитировать ссылки на переменные оболочки (например,"$f"
), если у вас нет веских причин не делать этого, и вы уверены, что знаете, что делаете. Это относится даже кecho "$f" | sed …
. Это также относится ко всему$(…)
(или`…`
) выражению; то естьmv "$f" "$(echo "$f" | sed "…")"
. … (Продолжение)mv
--
"$f" …
-
Теперь, когда вы знаете, какая кодировка используется для имен файлов на удаленном конце («latin1» - в соответствии с комментариями к первому ответу), вы также можете пойти по второму пути - запустить локальный termninal и ssh таким образом: способ, которым удаленные имена файлов отображаются правильно (а не первый способ: переименуйте их) .
Как и я , вы можете запустить терминал локально, который будет работать в этой специальной кодировке, например, так:
LC_ALL = en_US.latin1 xvt &
xvt
обозначает вашу терминальную программу.Возможно, существующая локаль называется
en_US.iso88591
, а неen_US.latin1
, как я предполагал.источник
Это не соответствует массовым требованиям, но у меня была похожая проблема, когда у меня было несколько версий файла со схожими именами, которые отличались только одним странным символом. К сожалению, это означало, что я не мог переименовать нарушителей, используя трюк с подстановочными знаками, который я обычно использую.
В конце я использовал Filezilla для подключения в качестве SFTP-клиента, просмотрел файлы и переименовал их с помощью графического интерфейса. Филезилла неплохо справился с хитрыми персонажами.
источник