Командная строка Linux: путаница с глобусом

POSIX требует такого поведения, поэтому в этом нет ничего необычного.

Из руководства POSIX vi :

ВХОДНЫЕ ФАЙЛЫ

См. Раздел ВВОДНЫЕ ФАЙЛЫ команды ex для описания входных файлов, поддерживаемых командой vi.

По следам руководства POSIX ex :

ВХОДНЫЕ ФАЙЛЫ

Входные файлы должны быть текстовыми файлами или файлами, которые будут текстовыми файлами, за исключением неполной последней строки, длина которой не превышает {LINE_MAX} -1 байт в длину и не содержит символов NUL. По умолчанию любая неполная последняя строка должна обрабатываться так, как если бы она имела завершающую . Редактирование других форм файлов может опционально быть разрешено реализациями ex.

Раздел OUTPUT FILES руководства vi также перенаправляет на ex:

OUTPUT FILES

Результатом ex должны быть текстовые файлы.

Пара определений POSIX:

3.397 Текстовый файл

Файл, содержащий символы, сгруппированные в ноль или более строк. Строки не содержат символов NUL, и длина ни одной из них не может превышать {LINE_MAX} байтов, включая символ . Хотя POSIX.1-2008 не делает различий между текстовыми файлами и двоичными файлами (см. Стандарт ISO C), многие утилиты выдают предсказуемый или осмысленный вывод только при работе с текстовыми файлами. Стандартные утилиты с такими ограничениями всегда указывают «текстовые файлы» в своих разделах STDIN или INPUT FILES.

3.206 Строка

Последовательность из нуля или более символов, отличных от , плюс завершающий символ .

Эти определения в контексте этих выдержек из страниц руководства означают, что, хотя соответствующая реализация ex / vi должна принимать искаженный текстовый файл, если единственной деформацией этого файла является отсутствие последней строки новой строки, при записи в буфер этого файла результат должен быть допустимым. текстовый файл.

Хотя в этом посте есть ссылка на издание стандарта POSIX 2013 г., соответствующие положения также появляются в гораздо более старом издании 1997 г. .

Наконец, если вы сочтете добавление новой строки ex нежелательным, вы почувствуете себя глубоко нарушенным нетерпимым изданием UNIX (1979) седьмого издания. Из руководства :

При чтении файла ed отбрасывает символы ASCII NUL и все символы после последней новой строки. Он отказывается читать файлы, содержащие символы, отличные от ASCII.

5
15.09.2017, 19:08
2 ответа

Если вы хотите переместить все файлы и каталоги со скрытыми именами (, начинающимися с точки ), в другое место:

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

По моему опыту, желание сделать что-то с полным -файлом или точечным -каталогом в каталоге возникает крайне редко.

5
27.01.2020, 20:33

Это сделано для устранения ошибки/неправильного функционирования в оболочках, отличных от 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).

Как примечание к истории, имена файлов, начинающиеся с ., являющиеся скрытыми файлами, были рождены из-за ошибки кодирования, когда кто-то пытался пропустить .и ..в первую очередь . По иронии судьбы, пытаясь сделать что-то со скрытыми файлами, мы столкнемся с той же проблемой.

9
27.01.2020, 20:33

Теги

Похожие вопросы