Я постоянно вижу ответы, цитирующие эту ссылку с указанием "Не разбирайся ls
!" Это беспокоит меня по нескольким причинам:
Кажется, что информация в этой ссылке была принята оптом с небольшим вопросом, хотя я могу выделить по крайней мере несколько ошибок при случайном чтении.
Также кажется, что проблемы, указанные в этой ссылке, не вызвали желания найти решение.
Из первого абзаца:
... когда вы запрашиваете
[ls]
список файлов, возникает огромная проблема: Unix позволяет использовать практически любой символ в имени файла, включая пробелы, символы новой строки, запятые, символы канала и почти все, что вы когда-либо пытались использовать в качестве разделитель, кроме NUL. ...ls
разделяет имена файлов с помощью новых строк. Это нормально, пока у вас нет файла с новой строкой в названии. И поскольку я не знаю какой-либо реализацииls
, позволяющей вам завершать имена файлов символами NUL вместо символов новой строки, мы не можем безопасно получить список имен файловls
.
Облом, верно? Как всегда мы можем справиться с новой строки завершается перечисленный набор данных для данных , которые могут содержать символы новой строки? Ну, если бы люди, отвечающие на вопросы на этом сайте, не делали такого рода вещи ежедневно, я мог бы подумать, что у нас были некоторые проблемы.
Правда в том, что большинство ls
реализаций на самом деле предоставляют очень простой API для анализа их вывода, и мы все делали это все время, даже не осознавая этого. Мало того, что вы можете завершить имя файла с нуля, вы также можете начать с нуля или с любой другой произвольной строки, которую вы можете пожелать. Более того, вы можете назначить эти произвольные строки для каждого типа файла . Пожалуйста примите к сведению:
LS_COLORS='lc=\0:rc=:ec=\0\0\0:fi=:di=:' ls -l --color=always | cat -A
total 4$
drwxr-xr-x 1 mikeserv mikeserv 0 Jul 10 01:05 ^@^@^@^@dir^@^@^@/$
-rw-r--r-- 1 mikeserv mikeserv 4 Jul 10 02:18 ^@file1^@^@^@$
-rw-r--r-- 1 mikeserv mikeserv 0 Jul 10 01:08 ^@file2^@^@^@$
-rw-r--r-- 1 mikeserv mikeserv 0 Jul 10 02:27 ^@new$
line$
file^@^@^@$
^@
Смотрите это больше.
Теперь это следующая часть этой статьи, которая действительно меня заводит:
$ ls -l
total 8
-rw-r----- 1 lhunath lhunath 19 Mar 27 10:47 a
-rw-r----- 1 lhunath lhunath 0 Mar 27 10:47 a?newline
-rw-r----- 1 lhunath lhunath 0 Mar 27 10:47 a space
Проблема в том, что из вывода
ls
ни вы, ни компьютер не можете определить, какие его части составляют имя файла. Это каждое слово? Это каждая строка? Нет. Нет правильного ответа на этот вопрос, кроме: вы не можете сказать.Также обратите внимание, как
ls
иногда искажает данные вашего имени файла (в нашем случае он превратил\n
символ между словами «a» и «newline» в знак вопроса ?)...
Если вы просто хотите перебрать все файлы в текущем каталоге, используйте
for
цикл и глобус:
for f in *; do
[[ -e $f ]] || continue
...
done
Автор называет это искажением имен файлов, когда ls
возвращает список имен файлов, содержащих глобусы оболочки, а затем рекомендует использовать глобус оболочки для получения списка файлов!
Учтите следующее:
printf 'touch ./"%b"\n' "file\nname" "f i l e n a m e" |
. /dev/stdin
ls -1q
f i l e n a m e
file?name
IFS="
" ; printf "'%s'\n" $(ls -1q)
'f i l e n a m e'
'file
name'
POSIX определяет-1
и -q
ls
операнды так:
-q
- Принудительно<tab>
записывать каждый экземпляр непечатных символов имени файла и s в виде знака вопроса ('?'
). Реализации могут предоставлять эту опцию по умолчанию, если вывод осуществляется на терминальное устройство.
-1
- (Цифровая цифра один.) Принудительно выводить по одной записи на строку.
Глобализация не без собственных проблем - ?
сопоставляет любой символ, поэтому несколько совпадающих ?
результатов в списке будут совпадать с одним файлом несколько раз. Это легко обрабатывается.
Хотя, как это сделать, дело не в этом - в конце концов, делать это не нужно, и это показано ниже - меня интересовало, почему нет . На мой взгляд, лучший ответ на этот вопрос был принят. Я бы посоветовал вам чаще концентрироваться на том, чтобы рассказать людям, что они могут сделать, чем на том, что они не могут. Я думаю, что вы намного менее вероятно окажетесь неправы, по крайней мере.
Но зачем даже пытаться? По общему признанию, моя главная мотивация состояла в том, что другие продолжали говорить мне, что я не мог. Я очень хорошо знаю, что ls
результат является настолько регулярным и предсказуемым, насколько вы могли бы пожелать, если вы знаете, что искать. Дезинформация беспокоит меня больше, чем большинство вещей.
Правда в том, что, за заметным исключением ответов как Патрика, так и Вумпа К. Уамбли (несмотря на удивительный дескриптор последнего) , я считаю, что большая часть информации в ответах здесь в основном правильная - глобус-оболочка более прост в использовании и, как правило, более эффективен при поиске в текущем каталоге, чем при разборе ls
. Они, однако, по крайней мере , в моем отношении, достаточно оснований , чтобы оправдать либо распространяя дезинформацию цитируемый в статье выше , ни они уважительная не « никогда не разобрать ls
. »
Обратите внимание, что непоследовательные результаты ответа Патрика в основном являются результатом его использования zsh
тогда bash
. zsh
- по умолчанию - $(
команда не разделяет )
результаты замены слова в переносимом виде. Итак, когда он спрашивает, куда делись остальные файлы? ответ на этот вопрос - ваша оболочка съела их. Вот почему вам нужно установить SH_WORD_SPLIT
переменную при использовании zsh
и работе с переносимым кодом оболочки. Я считаю его неспособность отметить это в своем ответе ужасно вводящим в заблуждение.
Ответ Wumpus не рассчитывается для меня - в контексте списка ?
персонаж является оболочкой. Я не знаю, как еще сказать это.
Чтобы обработать случай с несколькими результатами, вам нужно ограничить жадность глобуса. Следующее просто создаст тестовую базу ужасных имен файлов и покажет ее вам:
{ printf %b $(printf \\%04o `seq 0 127`) |
sed "/[^[-b]*/s///g
s/\(.\)\(.\)/touch '?\v\2' '\1\t\2' '\1\n\2'\n/g" |
. /dev/stdin
echo '`ls` ?QUOTED `-m` COMMA,SEP'
ls -qm
echo ; echo 'NOW LITERAL - COMMA,SEP'
ls -m | cat
( set -- * ; printf "\nFILE COUNT: %s\n" $# )
}
ВЫХОД
`ls` ?QUOTED `-m` COMMA,SEP
??\, ??^, ??`, ??b, [?\, [?\, ]?^, ]?^, _?`, _?`, a?b, a?b
NOW LITERAL - COMMA,SEP
?
\, ?
^, ?
`, ?
b, [ \, [
\, ] ^, ]
^, _ `, _
`, a b, a
b
FILE COUNT: 12
Теперь я буду в безопасности каждый символ , который не является /slash
, -dash
, :colon
или буквенно-цифрового символа в Glob оболочки затем sort -u
список для уникальных результатов. Это безопасно, потому ls
что уже убрал для нас любые непечатаемые символы. Часы:
for f in $(
ls -1q |
sed 's|[^-:/[:alnum:]]|[!-\\:[:alnum:]]|g' |
sort -u | {
echo 'PRE-GLOB:' >&2
tee /dev/fd/2
printf '\nPOST-GLOB:\n' >&2
}
) ; do
printf "FILE #$((i=i+1)): '%s'\n" "$f"
done
ВЫХОД:
PRE-GLOB:
[!-\:[:alnum:]][!-\:[:alnum:]][!-\:[:alnum:]]
[!-\:[:alnum:]][!-\:[:alnum:]]b
a[!-\:[:alnum:]]b
POST-GLOB:
FILE #1: '?
\'
FILE #2: '?
^'
FILE #3: '?
`'
FILE #4: '[ \'
FILE #5: '[
\'
FILE #6: '] ^'
FILE #7: ']
^'
FILE #8: '_ `'
FILE #9: '_
`'
FILE #10: '?
b'
FILE #11: 'a b'
FILE #12: 'a
b'
Ниже я снова подхожу к проблеме, но использую другую методологию. Помните, что - кроме \0
нуля - /
символ ASCII - единственный байт, запрещенный в имени пути. Здесь я откладываю globs и вместо этого комбинирую указанную -d
для POSIX опцию для ls
и указанную -exec $cmd {} +
для POSIX конструкцию для find
. Поскольку find
только когда-либо естественным образом будет генерироваться один /
из них последовательно, следующее легко обеспечивает рекурсивный и надежно разделенный список файлов, включающий всю информацию о дентри для каждой записи. Просто представьте, что вы можете сделать с чем-то вроде этого:
#v#note: to do this fully portably substitute an actual newline \#v#
#v#for 'n' for the first sed invocation#v#
cd ..
find ././ -exec ls -1ldin {} + |
sed -e '\| *\./\./|{s||\n.///|;i///' -e \} |
sed 'N;s|\(\n\)///|///\1|;$s|$|///|;P;D'
###OUTPUT
152398 drwxr-xr-x 1 1000 1000 72 Jun 24 14:49
.///testls///
152399 -rw-r--r-- 1 1000 1000 0 Jun 24 14:49
.///testls/?
\///
152402 -rw-r--r-- 1 1000 1000 0 Jun 24 14:49
.///testls/?
^///
152405 -rw-r--r-- 1 1000 1000 0 Jun 24 14:49
.///testls/?
`///
...
ls -i
может быть очень полезным - особенно когда речь идет об уникальности результата.
ls -1iq |
sed '/ .*/s///;s/^/-inum /;$!s/$/ -o /' |
tr -d '\n' |
xargs find
Это только самые портативные средства, которые я могу придумать. С GNU ls
вы можете сделать:
ls --quoting-style=WORD
И, наконец, вот гораздо более простой метод синтаксического анализа,ls
который я использую довольно часто, когда нужны номера инодов:
ls -1iq | grep -o '^ *[0-9]*'
Это просто возвращает номера инодов - это еще одна удобная опция, указанная в POSIX.
time bash -c 'for i in {1..1000}; do ls -R &>/dev/null; done'
= 3,18 сtime bash -c 'for i in {1..1000}; do echo **/* >/dev/null; done'
= 1,28 сstat
в своем ответе, поскольку он фактически проверяет, существует ли каждый файл. Ваш бит внизу сsed
вещью не работает.ls
? То, что вы описываете, очень сложно. Мне нужно разобрать его, чтобы понять все это, и я относительно компетентный пользователь. Вы не можете ожидать, что ваш средний Джо сможет справиться с чем-то вроде этого.ls
вывод синтаксического анализа является неправильным, были хорошо освещены в исходной ссылке (и во многих других местах). Этот вопрос был бы разумным, если бы ОП просил помочь понять его, но вместо этого ОП просто пытается доказать, что его неправильное использование в порядке.parsing ls is bad
. Делатьfor something in $(command)
и полагаться на разделение слов для получения точных результатов плохо для большинства изcommand's
них, у которых нет простого вывода.Ответы:
Я совсем не уверен в этом, но давайте предположим, ради аргумента, что вы могли бы , если готовы приложить достаточные усилия,
ls
надежно проанализировать результаты , даже перед лицом «противника» - человека, который знает код, который вы написали, и сознательно выбирает имена файлов, предназначенные для его взлома.Даже если бы вы могли это сделать, это все равно было бы плохой идеей .
Оболочка Борна не очень хороший язык. Его не следует использовать для чего-либо сложного, если только крайняя переносимость не важнее любого другого фактора (например
autoconf
).Я утверждаю, что если вы столкнулись с проблемой, когда синтаксический анализ выходных данных
ls
выглядит как путь наименьшего сопротивления для сценария оболочки, это убедительный признак того, что все, что вы делаете, слишком сложно для оболочки, и вы должны переписать все это в Perl или Python. Вот ваша последняя программа на Python:Это не имеет никаких проблем с необычными символами в именах файлов - вывод является неоднозначным, точно так же, как вывод
ls
неоднозначен, но это не имеет значения в «реальной» программе (в отличие от демонстрационной версии, подобной этой), которая будет использовать результатos.path.join(subdir, f)
напрямую.Не менее важно, и в резком контрасте с тем, что вы написали, оно будет иметь смысл через шесть месяцев, и его будет легко изменить, если вам нужно сделать что-то немного другое. В качестве иллюстрации предположим, что вы обнаружили необходимость исключить точечные файлы и резервные копии редактора и обработать все в алфавитном порядке по базовому имени:
источник
for in | for in
говорит о рекурсии? Я не уверен. Даже если это не может быть больше, чем один, верно? Это единственный ответ, который имеет смысл для меня до сих пор.for
циклы.os.walk
за кулисами идет серьезная тяжелая работа, но вам не нужно беспокоиться об этом больше, чем о том, какls
или как выfind
работаете внутри.os.walk
возвращает объект генератора . Генераторы - это ленивые списки Python. Каждый раз, когда внешний цикл for повторяется, генератор вызывается и «возвращает» содержимое другого подкаталога. Эквивалентная функциональность в Perl естьFile::Find
, если это поможет.ls
вывода.На эту ссылку часто ссылаются, потому что информация абсолютно точна, и она была там очень давно.
ls
заменяет непечатные символы глобальными символами да, но эти символы не указаны в имени файла. Почему это важно? 2 причины:Например:
Обратите внимание, что у нас есть 2 файла, которые выглядят одинаково. Как вы собираетесь отличить их, если они оба представлены как
a?b
?Здесь есть разница. Когда вы возвращаете глобус, как показано, этот глобус может соответствовать более чем одному файлу. Однако, когда вы просматриваете результаты, соответствующие глобу, вы получаете точный файл, а не глобус.
Например:
Обратите внимание, как
xxd
вывод показывает, что$file
содержит необработанные символы,\t
а\n
не?
.Если вы используете
ls
, вы получите это вместо:"В любом случае я собираюсь повторить, почему бы не использовать
ls
?"Ваш пример, который вы привели, на самом деле не работает. Похоже, это работает, но это не так.
Я имею в виду это:
Я создал каталог с кучей имен файлов:
Когда я запускаю ваш код, я получаю это:
Куда делись остальные файлы?
Давайте попробуем это вместо этого:
Теперь давайте используем реальный глобус:
С баш
Приведенный выше пример был с моей обычной оболочкой, zsh. Когда я повторяю процедуру с bash, я получаю другой совершенно другой набор результатов на вашем примере:
Тот же набор файлов:
Радикально разные результаты с вашим кодом:
С оболочкой, это прекрасно работает:
Причина, по которой bash ведет себя таким образом, восходит к одному из моментов, которые я указывал в начале ответа: «Глобус файла может соответствовать более чем одному файлу».
ls
возвращает один и тот же glob (a?b
) для нескольких файлов, поэтому каждый раз, когда мы расширяем этот глобус, мы получаем каждый файл, соответствующий ему.Как воссоздать список файлов, которые я использовал:
Шестнадцатеричный код - это символы UTF-8 NBSP.
источник
ls
. Я также попросил вас проверить свой код, так как он не работает. Какое отношение zsh имеет к этому?Давайте попробуем немного упростить:
Видеть? Это уже неправильно прямо здесь. Есть 3 файла, но bash сообщает 4. Это потому, что
set
ему передаются глобусы, сгенерированные,ls
которые раскрываются оболочкой перед передачейset
. Вот почему вы получаете:Или, если вы предпочитаете:
Выше был запущен
bash 4.2.45
.источник
ls -1qRi | grep -o '^ *[0-9]*'
- это парсингls
вывода, чувак, и это самый быстрый и лучший из известных мне способов получения списка номеров инодов.Вывод
ls -q
вообще не глобус. Используется?
для обозначения «Здесь есть символ, который не может быть отображен напрямую». Глобусы используют?
для обозначения «Любой символ разрешен здесь».Глобусы имеют другие специальные символы (
*
и,[]
по крайней мере, и внутри[]
пары их больше). Никто из них не избежалls -q
.Если вы обрабатываете
ls -1q
вывод, есть набор глобусов и расширяете их, вы не только получитеx
дважды, но и пропустите[x]
полностью. Как глобус, он не соответствует себе как строка.ls -q
предназначен для того, чтобы спасти ваши глаза и / или терминал от сумасшедших персонажей, а не для того, чтобы создавать что-то, что вы можете передать обратно в оболочкуисточник
Ответ прост:
ls
ваши особые случаи должны перевешивать любую возможную выгоду. Этих особых случаев можно избежать, если вы не анализируетеls
вывод.Здесь мантра никогда не доверяет файловой системе пользователя (эквивалент никогда не доверять пользовательскому вводу ). Если есть метод, который будет работать всегда, со 100% уверенностью, то это должен быть метод, который вы предпочитаете, даже если он
ls
делает то же самое, но с меньшей уверенностью. Я не буду вдаваться в технические детали, так как они были подробно рассмотрены Тердоном и Патриком . Я знаю, что из-за рисков использованияls
в важной (и, возможно, дорогостоящей) транзакции, когда моя работа / престиж находится на линии, я предпочту любое решение, которое не имеет степени неопределенности, если его можно избежать.Я знаю, что некоторые люди предпочитают некоторый риск , а не уверенность , но я подал отчет об ошибке .
источник
Причина, по которой люди говорят, что никогда не делают что-то, не обязательно, потому что это абсолютно положительно не может быть сделано правильно. Мы можем сделать это, но это может быть более сложным, менее эффективным как в пространственном, так и во временном отношении. Например, было бы прекрасно сказать: «Никогда не создавайте большой бэкэнд для электронной коммерции в сборке x86».
Итак, теперь к проблеме: как вы уже продемонстрировали, вы можете создать решение, которое анализирует ls и дает правильный результат - так что правильность не проблема.
Это сложнее? Да, но мы можем скрыть это за вспомогательной функцией.
Итак, теперь к эффективности:
Эффективность использования пространства. Ваше решение основано на
uniq
фильтрации дубликатов, поэтому мы не можем генерировать результаты лениво. Так что либоO(1)
против,O(n)
либо у обоихO(n)
.Эффективность по времени: в лучшем случае
uniq
используется подход с хэш-картой, поэтому у нас все еще естьO(n)
алгоритм по количеству закупаемых элементов , хотя, возможно, так и естьO(n log n)
.Теперь реальная проблема: в то время как ваш алгоритм все еще не выглядит слишком плохо, я был очень осторожен, чтобы использовать закупаемые элементы, а не элементы для n Потому что это имеет большое значение. Скажем, у вас есть файл
\n\n
, в результате которого будет отображаться глобус,??
поэтому сопоставляйте каждый 2-символьный файл в списке Как ни странно, если у вас есть другой файл\n\r
, который также приведет к??
возвращению всех двухсимвольных файлов. Видите, куда это идет? Экспоненциальное, а не линейное поведение, безусловно, квалифицируется как «худшее поведение во время выполнения». В этом разница между практическим алгоритмом и алгоритмом, о котором вы пишете в теоретических журналах по CS.Все любят примеры, верно? Вот так. Создайте папку с именем «test» и используйте этот сценарий python в том же каталоге, где находится папка.
Единственное, что он делает - генерирует все продукты длиной 3 для 7 символов. Математика средней школы говорит нам, что должно быть 343 файла. Ну, это должно быть очень быстро печатать, так что давайте посмотрим:
Теперь давайте попробуем ваше первое решение, потому что я действительно не могу получить это
вещь здесь, чтобы работать на Linux Mint 16 (который, я думаю, говорит о многом для удобства использования этого метода).
В любом случае, поскольку вышеприведенное в значительной степени фильтрует результат только после его получения, более раннее решение должно быть, по крайней мере, таким же быстрым, как и более поздние (в этом нет никаких хитростей с инодами, но они ненадежны, поэтому вы бы отказались от правильности).
Так что теперь, как долго
брать? Ну, я действительно не знаю, нужно время, чтобы проверить 343 ^ 343 имен файлов - я скажу вам после смерти вселенной.
источник
Заявленные намерения ОП
Предисловие и обоснование оригинального ответа † обновлено 2015-05-18
В последнем обновлении своего вопроса mikeserv (ОП) заявил: «Я действительно считаю позором то, что впервые задал этот вопрос, чтобы указать на источник дезинформации, и, к сожалению, наиболее одобренный ответ здесь в значительной степени вводит в заблуждение. "
Ну ладно; Я чувствую, что это был довольно позор, что я потратил так много времени, пытаясь понять, как объяснить свое значение, только чтобы найти его , когда я перечитал вопрос. Этот вопрос закончил тем, что «[порождал] обсуждение, а не ответы» ‡ и в итоге занял примерно 18 КБ текста (только для вопроса, чтобы быть ясным), что было бы долго даже для сообщения в блоге.
Но StackExchange - это не ваша мыльница и не ваш блог. Однако, по сути, вы использовали его как минимум для обоих. Люди заканчивали тем, что тратили много времени, отвечая на ваши вопросы, вместо того, чтобы отвечать на реальные вопросы людей. На этом этапе я буду отмечать вопрос как не очень подходящий для нашего формата, учитывая, что ФП прямо заявил, что он вообще не был задуман как вопрос.
На данный момент я не уверен, был ли мой ответ к сути или нет; возможно нет, но он был направлен на некоторые ваши вопросы, и, возможно, это может быть полезным ответом кому-то еще; начинающие отваживаются, некоторые из них «не превращаются» в «иногда делают», когда вы становитесь более опытным. :)
Как общее правило...
пожалуйста, прости оставшиеся грубые края; я потратил слишком много времени на это уже ... вместо того, чтобы цитировать ОП напрямую (как первоначально предполагалось), я попытаюсь обобщить и перефразировать.
[в значительной степени переработанный из моего первоначального ответа]
после рассмотрения, я считаю, что я неправильно прочитал акцент, который ФП придавал вопросам, на которые я отвечал; Тем не менее, затронутые вопросы были подняты, и я оставил ответы в значительной степени нетронутыми, так как я считаю, что они актуальны и решают проблемы, которые я видел, поднятые в других контекстах, а также в отношении рекомендаций для начинающих.
В оригинальной публикации несколько раз спрашивалось, почему в разных статьях даются советы, такие как «Не анализировать
ls
вывод» или «Никогда не анализироватьls
вывод» и т. Д.Мое предлагаемое решение проблемы заключается в том, что примеры такого рода утверждений являются просто примерами идиомы, сформулированной несколько иными способами, в которой абсолютный квантификатор сочетается с императивом [например, «не [никогда] X», «[Вы должны] всегда Y», «[не следует] никогда Z»], чтобы сформировать утверждения, предназначенные для использования в качестве общих правил или указаний, особенно когда они даны новичкам в предмете, а не предназначены для абсолютных истин, очевидная форма этих заявлений, несмотря на.
Когда вы начинаете изучать новый предмет, и если у вас нет четкого понимания того, почему вам, возможно, придется поступить иначе, хорошей идеей будет просто следовать принятым общим правилам без исключения - если только под руководством кого-то более опытного это сам. С повышением квалификации и опыта вы сможете в дальнейшем определять, когда и применяется ли правило в конкретной ситуации. Как только вы действительно достигнете значительного уровня опыта, вы, скорее всего, сначала поймете причины, лежащие в основе общего правила, и с этого момента вы сможете начать использовать свое суждение относительно того, применяются ли и на каком уровне причины, лежащие в основе правила, в эта ситуация, а также относительно того, есть ли, возможно, основные проблемы.
И именно тогда, возможно, эксперт может сделать что-то с нарушением «Правил». Но это не сделало бы их менее «Правилами».
И, поэтому, к данной теме: на мой взгляд, просто потому, что эксперт может нарушить это правило, не будучи полностью сбитым с толку, я не вижу способа, которым вы могли бы оправдать сообщение начинающего, что «иногда» это хорошо, чтобы разобрать
ls
вывод, потому что: это не так . Или, по крайней мере, конечно, для новичка это неправильно.Вы всегда кладете свои пешки в центр; в открытии один кусок, один ход; замок при первой возможности; рыцари перед епископами; рыцарь на краю мрачен; и всегда следите за тем, чтобы вы могли видеть свои расчеты до конца! (Ой, простите, устаю, это для шахматного StackExchange.)
Правила, которые должны быть нарушены?
При чтении статьи на тему, которая предназначена или может быть прочитана новичками, часто вы увидите такие вещи:
Хотя эти утверждения, безусловно, утверждают абсолютные и неподвластные времени правила, это не так; вместо этого это способ формулирования общих правил [так называемых «руководящих принципов», «практических правил», «основ» и т. д.], по крайней мере, возможно, один из подходящих способов сформулировать их для начинающих, которые могут читать эти статьи. Тем не менее, только потому, что они заявлены как абсолютные, правила, безусловно, не связывают профессионалов и экспертов [которые, вероятно, были теми, кто суммировал такие правила в первую очередь, как способ записать и передать знания, полученные, когда они имели дело с повторяющимися проблемы в их конкретном ремесле.]
Эти правила, конечно, не раскрывают, как эксперт будет иметь дело со сложной или нюансированной проблемой, в которой, скажем, эти правила противоречат друг другу; или в которых проблемы, которые привели к правилу, в первую очередь просто не применяются. Эксперты не боятся (или не должны бояться!) Просто нарушать правила, которые, как они случайно знают, не имеют смысла в конкретной ситуации. Эксперты постоянно сталкиваются с уравновешиванием различных рисков и проблем в своем ремесле и должны часто использовать свое суждение, чтобы решить нарушать такого рода правила, вынуждены уравновешивать различные факторы и не могут просто полагаться на таблицу правил, которой нужно следовать. Возьмите
Goto
в качестве примера: были долгие, повторяющиеся дебаты о том, вредны ли они. (Да, не всегда используют последовательно открывает;. D)Модальное предложение
Странная особенность, по крайней мере в английском, и я полагаю, во многих других языках общих правил, заключается в том, что они изложены в той же форме, что и модальное предложение, однако эксперты в данной области готовы дать общее правило для ситуации, все время зная, что они нарушат правило, когда это уместно. Поэтому ясно, что эти утверждения не должны быть эквивалентны тем же утверждениям в модальной логике.
Вот почему я говорю, что они должны быть просто идиоматичными. Вместо того, чтобы действительно быть «никогда» или «всегда», эти правила обычно служат для кодификации общих руководящих принципов, которые, как правило, подходят в широком диапазоне ситуаций, и которые, когда начинающие следуют им слепо, могут привести к лучшие результаты, чем новичок, решивший пойти против них без веской причины. Иногда они кодифицируют правила, просто приводя к некачественным результатам, а не к прямым неудачам, сопровождающим неправильный выбор при нарушении правил.
Таким образом, общие правила не являются абсолютными модальными суждениями, которые они кажутся на поверхности, но вместо этого являются кратким способом дать правило с подразумеваемым стандартным образцом, что-то вроде следующего:
где, конечно, вы могли бы заменить «никогда не анализировать
ls
вывод» вместо $ {RULE}. :)О да! Как насчет синтаксического анализа
ls
вывода?Ну, так что, учитывая все это ... я думаю, довольно ясно, что это правило хорошее. Прежде всего, настоящее правило следует понимать как идиоматическое, как объяснено выше ...
Но, кроме того, дело не только в том, что вам нужно хорошо разбираться в сценариях оболочки, чтобы знать, можно ли его сломать, в каком-то конкретном случае. Кроме того, требуется столько же умения, чтобы сказать, что вы ошиблись, когда пытаетесь сломать его при тестировании! И я уверенно говорю, что очень большая часть вероятной аудитории таких статей (давая советы типа «Не разбирай результат
ls
!») Не может делать такие вещи , и те, у кого есть такой навык, вероятно, поймут, что они понимают это самостоятельно и игнорируют правило так или иначе.Но ... просто посмотрите на этот вопрос, и как даже люди, которые, вероятно, обладают навыком, думали, что это плохой призыв; и сколько усилий автор вопроса потратил только на то, чтобы добраться до точки текущего лучшего примера! Я гарантирую вам, что проблема сложная, 99% людей ошибаются и могут привести к очень плохим результатам! Даже если выбранный метод окажется хорошим; пока эта (или другая)
ls
идея синтаксического анализа не будет принята ИТ-специалистами / разработчиками в целом, выдержит много испытаний (особенно испытание временем) и, наконец, не сможет перейти к статусу «общей техники», вероятно, что Многие люди могут попробовать и ошибиться ... с катастрофическими последствиями.Итак, еще раз повторю ... что, особенно в этом случае , вот почему " никогда не анализировать
ls
вывод!" это определенно правильный способ выразить это.[ОБНОВЛЕНИЕ 2014-05-18: разъяснены причины ответа (выше), чтобы ответить на комментарий от ОП; следующее дополнение является ответом на дополнения ФП к вчерашнему вопросу]
[ОБНОВЛЕНИЕ 2014-11-10: добавлены заголовки и реорганизован / реорганизован контент; а также: переформатирование, переписывание, уточнение, и ... "сжато-если" ... я хотел, чтобы это было просто очисткой, хотя это и превратилось в небольшую переработку. Я оставил это в плачевном состоянии, поэтому я в основном пытался отдать ему приказ. я чувствовал, что важно оставить первый раздел без изменений; поэтому есть только два небольших изменения: избыточное «но» удалено и «это» подчеркнуто.]
† Первоначально я задумал это исключительно как пояснение к своему оригиналу; но определился с другими дополнениями после размышления
‡ см. Https://unix.stackexchange.com/tour для получения рекомендаций по сообщениям.
источник
ls
!» Это правильный совет: 1. продемонстрируйте (к вашему удовлетворению), что каждый вариант использования, в котором можно проанализироватьls
вывод, имеет другое доступное решение, превосходящее в некотором смысле, без этого. 2. показать, что в приведенных случаях утверждение не является буквальным.ls
это компьютерная утилита - вы можете анализировать вывод компьютера.Можно ли разобрать вывод
ls
в определенных случаях? Конечно. Идея извлечения списка номеров инодов из каталога является хорошим примером - если вы знаете, что ваша реализацияls
поддерживает-q
, и, следовательно, каждый файл будет выдавать ровно одну строку вывода, и все, что вам нужно, это номера инодов, анализируя их изls -Rai1q
выход, безусловно, является возможным решением. Конечно, если бы автор раньше не видел совета типа «Никогда не анализировать вывод ls», он, вероятно, не подумал бы о именах файлов с символами новой строки в них, и, вероятно, в результате пропустил бы «q», и в этом крайнем случае код будет слегка нарушен, поэтому даже в тех случаях, когдаls
вывод синтаксического анализа является разумным, этот совет все еще полезен.Чем шире Дело в том , что, когда новичок в языке сценариев командной оболочки пытается иметь фигуру сценария из (например) , что это самый большой файл в каталоге, или то , что это совсем недавно измененный файл в каталоге, его первый инстинкт для разбора
ls
«ю.ш. вывод - понятен, потому чтоls
это одна из первых команд, которую изучает новичок.К сожалению, этот инстинкт неправильный, и этот подход нарушен. Более того, к сожалению, он слегка сломан - он будет работать большую часть времени, но не получится в крайних случаях, которые, возможно, могут быть использованы кем-то со знанием кода.
Новичок может подумать о
ls -s | sort -n | tail -n 1 | awk '{print $2}'
как способ получить самый большой файл в каталоге. И это работает, пока у вас нет файла с пробелом в имени.Хорошо, так как насчет
ls -s | sort -n | tail -n 1 | sed 's/[^ ]* *[0-9]* *//'
? Работает нормально, пока у вас нет файла с новой строкой в имени.Поможет ли добавление
-q
кls
аргументам, когда в имени файла есть новая строка? Это может выглядеть так, пока у вас не появятся 2 разных файла, которые содержат непечатаемый символ в одном месте в имени файла, а затемls
вывод не позволит вам определить, какой из них был самым большим. Хуже того, чтобы расширить «?», Он, вероятно, прибегает к своей оболочкеeval
- что вызовет проблемы, если он попадет в файл с именем, например,Помогает ли
--quoting-style=shell
(если вашаls
даже поддерживает)? Нет, все еще показывает? для непечатаемых символов, так что все еще неоднозначно, какое из нескольких совпадений было самым большим.--quoting-style=literal
? Нет, то же самое.--quoting-style=locale
или же--quoting-style=c
может помочь, если вам просто нужно однозначно напечатать имя самого большого файла, но, вероятно, нет, если вам нужно потом что-то сделать с файлом - это будет куча кода, чтобы отменить кавычки и вернуться к реальному имени файла, так что вы можете передать его, скажем, GZIP.И в конце всей этой работы, даже если то, что у него есть, является безопасным и правильным для всех возможных имен файлов, это нечитабельно и не поддерживается, и его можно было бы сделать намного проще, безопаснее и читабельнее в python, perl или ruby.
Или даже используя другие инструменты оболочки - вне головы, я думаю, что это должно сработать:
И должен быть как минимум таким же портативным, как
--quoting-style
есть.источник