POSIX требует такого поведения, поэтому в этом нет ничего необычного.
Из руководства POSIX vi :
ВХОДНЫЕ ФАЙЛЫ
См. Раздел ВВОДНЫЕ ФАЙЛЫ команды ex для описания входных файлов, поддерживаемых командой vi.
По следам руководства POSIX ex :
ВХОДНЫЕ ФАЙЛЫ
Входные файлы должны быть текстовыми файлами или файлами, которые будут текстовыми файлами, за исключением неполной последней строки, длина которой не превышает {LINE_MAX} -1 байт в длину и не содержит символов NUL. По умолчанию любая неполная последняя строка должна обрабатываться так, как если бы она имела завершающую . Редактирование других форм файлов может опционально быть разрешено реализациями ex.
Раздел OUTPUT FILES руководства vi также перенаправляет на ex:
OUTPUT FILES
Результатом ex должны быть текстовые файлы.
Пара определений POSIX:
Файл, содержащий символы, сгруппированные в ноль или более строк. Строки не содержат символов NUL, и длина ни одной из них не может превышать {LINE_MAX} байтов, включая символ . Хотя POSIX.1-2008 не делает различий между текстовыми файлами и двоичными файлами (см. Стандарт ISO C), многие утилиты выдают предсказуемый или осмысленный вывод только при работе с текстовыми файлами. Стандартные утилиты с такими ограничениями всегда указывают «текстовые файлы» в своих разделах STDIN или INPUT FILES.
Последовательность из нуля или более символов, отличных от , плюс завершающий символ .
Эти определения в контексте этих выдержек из страниц руководства означают, что, хотя соответствующая реализация ex / vi должна принимать искаженный текстовый файл, если единственной деформацией этого файла является отсутствие последней строки новой строки, при записи в буфер этого файла результат должен быть допустимым. текстовый файл.
Хотя в этом посте есть ссылка на издание стандарта POSIX 2013 г., соответствующие положения также появляются в гораздо более старом издании 1997 г. .
Наконец, если вы сочтете добавление новой строки ex нежелательным, вы почувствуете себя глубоко нарушенным нетерпимым изданием UNIX (1979) седьмого издания. Из руководства :
При чтении файла ed отбрасывает символы ASCII NUL и все символы после последней новой строки. Он отказывается читать файлы, содержащие символы, отличные от ASCII.
Если вы хотите переместить все файлы и каталоги со скрытыми именами (, начинающимися с точки ), в другое место:
mv.[^.]* old-dot-files/
Или всякий раз, когда вы хотите что-то сделать со всеми точечными -файлами или точечными -каталогами в каталоге:
for name in.[^.]*; do
# process "$name"
done
Обратите внимание, что шаблон .??*
требует, чтобы совпадающие имена содержали не менее трех символов, поэтому имена, подобные .a
, не будут выбраны. .[^.]*
, с другой стороны, пропустит все, что содержит двойную точку в начале имени.
Возможно, будет лучше явно проверить совпадающие имена:
for name in.*; do
# expecting a regular file
if [ -f "$name" ]; then
# process "$name"
fi
done
for name in.*; do
# expecting a directory other than. and..
if [ -d "$name" ] && [ "$name" != '.' ] && [ "$name != '..' ]; then
# process "$name"
fi
done
По моему опыту, желание сделать что-то с полным -файлом или точечным -каталогом в каталоге возникает крайне редко.
Это сделано для устранения ошибки/неправильного функционирования в оболочках, отличных от zsh
,fish
и потомки оболочки Форсайта (, включая pdksh
и производные ), посредством чего глобусы .*
включают .
и..
(в системах (, к сожалению, ), где readdir()
возвращает их)
Этими снарядами,
chmod -R og-rwx.*
например, будет рекурсивно удалять разрешения rwx для текущего и родительского каталога, а не только для скрытых файлов и каталогов в текущем каталоге. Для этого пришлось добавить обходной путь rm
, так как слишком много людей споткнулись о rm -rf.*
.
Это также (вероятно, чаще )используется для передачи всех файлов (скрытых или нет )в качестве аргументов для команды (cmd.[!.]*..?* *
), для которой вы найдете другие обходные пути в зависимости от оболочка .
Это особенно плохо для команд, которые делают что-то рекурсивно или работают с каталогами, такими как ls.*
, chown -R.*
, find.*
, grep -r blah.*
, но это все еще раздражает для большинства других команд, и я не могу придумать ни одной команды для которые вы хотели бы, чтобы эти .
и ..
были включены в список файлов, переданных им.
Глоб .[^.]*
(.[!.]*
в оболочках Bourne/POSIX )исключает .
(, так как он совпадает с именами файлов, содержащими по крайней мере два символа )и ..
(, так как второй символ — .
, который не не соответствует [^.]
), но также исключает такие файлы, как ..foo
, для которых вам нужен второй глобус ..?*
.
Эти .
и ..
являются инструментами для обхода каталогов, ошибочно указывать их как обычные файлы. POSIX требует, чтобы они понимались в компонентах пути (, как в open(".")
, stat("foo/../bar")
), но не обязательно реализовывались как элементы каталога и не включались в readdir()
.
Тем не менее, большинство систем по-прежнему реализуют те, что были в ранних версиях Unices, в виде жестких ссылок, а те, которые этого не делают, по-прежнему будут подделывать записи для них в выводе getdents()
/ readdir()
.
С bash
,альтернативой является включение опции dotglob
и использование:
chmod -R og-rwx [.]*
(однако имейте в виду, что если нет скрытого файла, отличного от -, он может изменить права доступа к файлу [.]*
, если только у вас не была включена опция failglob
для имитации поведения zsh
/fish
).
Как примечание к истории, имена файлов, начинающиеся с .
, являющиеся скрытыми файлами, были рождены из-за ошибки кодирования, когда кто-то пытался пропустить .
и ..
в первую очередь . По иронии судьбы, пытаясь сделать что-то со скрытыми файлами, мы столкнемся с той же проблемой.