Я предполагаю, что Вы видите это �
недопустимый символ, потому что имя содержит последовательность байта, которая не является допустимым UTF-8. Имена файлов в типичных файловых системах Unix (включая Ваш) являются строками байтов, и это до приложений для выбора что кодирование использовать. В наше время существует тенденция для использования UTF-8, но это не универсально, особенно в локалях, которые никогда не могли жить с плоскостью ASCII и использовали другую кодировку прежде, чем UTF-8 даже существовал.
Попробовать LC_CTYPE=en_US.iso88591 ls
видеть, имеет ли имя файла смысл в ISO-8859-1 (латинский 1). Если это не делает, попробуйте другие локали. Отметьте это только LC_CTYPE
установка локали имеет значение здесь.
В локали UTF-8 следующая команда покажет Вам всем файлы, имя которых не является допустимым UTF-8:
grep-invalid-utf8 () {
perl -l -ne '/^([\000-\177]|[\300-\337][\200-\277]|[\340-\357][\200-\277]{2}|[\360-\367][\200-\277]{3}|[\370-\373][\200-\277]{4}|[\374-\375][\200-\277]{5})*$/ or print'
}
find | grep-invalid-utf8
Можно проверить, имеют ли они больше смысла в другой локали с перекодом или iconv:
find | grep-invalid-utf8 | recode latin1..utf8
find | grep-invalid-utf8 | iconv -f latin1 -t utf8
После того как Вы решили, что набор имен файлов находится в определенном кодировании (например, latin1), один способ переименовать их
find | grep-invalid-utf8 |
rename 'BEGIN {binmode STDIN, ":encoding(latin1)"; use Encode;}
$_=encode("utf8", $_)'
Это использует жемчуг, переименовывают команду, доступную на Debian и Ubuntu. Можно передать его -n
показать то, что это обошлось бы без фактического переименования файлов.
Если Вы читаете символ за один раз с read -n
, необходимо будет реализовать синтаксический анализатор сочетания клавиш. Можно создать медленное-и-грязное решение, которое работает над большинством терминалов с этим: полагайте, что escape-последовательность функциональной клавиши начинается с символа ESC и продолжает любое количество символов среди 0-9;[]O
сопровождаемый одним последним символом не в этом наборе.
Лучший способ считать вход состоит в том, чтобы пользоваться надлежащей входной библиотекой. Bash использует один в его собственных целях (readline). Вы получаете ограниченный интерфейс к нему путем объявления собственных привязок клавиш с bind
встроенный; конкретно bind -x
выполнять команду оболочки на нажатии клавиши. Из-за этого ограниченного интерфейса реализовывая то, что Вы хотите, вероятно, будет возможно, но трудно.
Zsh имеет свою собственную входную библиотеку, zle. Его интерфейс намного более богат, чем удар. С zle можно определить произвольные контурные карты, и Вы получаете больше доступа к внутренностям zle из кода оболочки. Использовать zle
присваивать оболочку функционирует к zle пользовательским командам (названный виджетами), bindkey
создать и заполнить Вашу собственную контурную карту, и наконец vared
считать строку входа с помощью контурной карты по Вашему выбору.
Можно поместить терминал в режим без предварительной обработки после первого read
если существует esc
символ, и затем использует секунду read
считать и проанализировать остающиеся байты если любой (cf. Травма символа ESC Bash и видит также arrows.txt).
#!/bin/bash
# tested on Mac OS X 10.6.8
IFS=$'\n'
old_tty_settings="$(stty -g)"
exec 0</dev/tty
tput smir # enable insert mode
while IFS="" read -r -s -n1 key; do # first read (reads only a single byte)
#od -c <<<"$key"
#continue
((${#key}==0)) && break
case "$key" in
$'\001') printf '\r' # ctrl-a
continue;;
$'\177') tput rmir
printf "\010\040\010\033[P" # backspace
tput smir
continue;;
$'\025') printf "\033[1K" # tput el1 does not work on Mac OS X 10.6.8
continue;; # ctrl-u (clear to start of line)
$'\v') tput el
continue;; # ctrl-k (clear to end of line)
esac
# if the first char is esc (i.e. \e or \033 respectively)
if [[ "$key" == $'\033' ]]; then
stty cbreak -echo min 0 time 0 # set raw terminal
IFS="" read -r bytes # second read (reads remaining bytes)
if [[ ${#bytes} -gt 0 ]]; then
stty "$old_tty_settings"
case "${key}${bytes}" in
$'\033[3~') tput dch1 # delete one char
continue;;
esac
printf "${key}${bytes}"
else
stty "$old_tty_settings"
fi
else
#stty "$old_tty_settings"
printf '%s' "$key"
fi
done
echo
exit 0
read -n
метод, работающий достаточно хорошо, но я сейчас понял этоtmux
иscreen
используйте различные привязки клавиш для ДОМА и КОНЦА, чем делаютkonsole
иgnome-terminal
без мультиплексоров... Возможно, это - emacs по сравнению с vi проблемой привязки клавиш... Я добираюсь там, и 'readline' метод начинает иметь некоторый смысл мне теперь, но я должен придерживаться сread -n 1
на данный момент. Это достаточно довольно быстро (но медленно для записи :). Когда я закончил, я далее посмотрю на readline. – Peter.O 09.08.2011, 22:33