Если Вы загружаете исходный код (т.е. не пакеты от Вашего распределения) он будет обычно содержать настраивать сценарий, который позволяет Вам указывать, где установить скомпилированное программное обеспечение. Это обычно значения по умолчанию к /usr/local
. Можно изменить это при помощи следующей опции:
$ ./configure --prefix=/foo
Не все программное обеспечение сделано этот путь, но необычно не быть. Так как Ваше распределение устанавливает программное обеспечение под/usr, это означает, что у Вас будет две версии в Вашей системе. При установке ffmpeg на/opt/ffmpeg необходимо было бы просто добавить двоичный каталог (вероятно,/opt/ffmpeg/bin) к ПУТИ.
Если Вы действительно интересуетесь источником, смотрите на Linux С нуля и хинду.
§ Word Splitting Эти команды могут быть выполнены без ошибок
Я не призываю пользователей принять такое поведение, но если кто-то решительно понимает, когда происходит разделение слов, тогда они должны быть в состоянии решить за себя, когда использовать кавычки.[1178400]
Насколько мне известно, есть только два случая, в которых необходимо заключать расширения в двойные кавычки, и в этих случаях используются два специальных параметра оболочки "$ @"
и "$ * "
- которые указаны в двойных кавычках, чтобы раскрывать их по-разному. Во всех остальных случаях (исключая, возможно, специфичные для оболочки реализации массивов) поведение раскрытия является настраиваемой вещью - для этого есть варианты.
Это, конечно, не означает, что следует избегать использования двойных кавычек - наоборот, это, вероятно, самый удобный и надежный метод ограничения расширения, который может предложить оболочка. Но, я думаю, поскольку альтернативы уже были искусно изложены, это отличное место для обсуждения того, что происходит, когда оболочка расширяет значение.
Оболочка по своей сути и душе (для тех, у кого они есть) является интерпретатором команд - это синтаксический анализатор, подобный большому интерактивному sed
. Если ваш оператор оболочки подавляет пробелами или что-то подобное, то это очень вероятно, потому что вы не полностью поняли процесс интерпретации оболочки - особенно, как и почему он переводит оператор ввода в действенный команда. Задача оболочки состоит в следующем:
принять ввод
интерпретировать и правильно разделить на токенизированный ввод слова
ввод слова являются элементами синтаксиса оболочки, такими как $ word
или echo $ words 3 4 * 5
слов всегда разделяются на пробелы - это всего лишь синтаксис - но только буквальные символы пробелов передаются оболочке во входном файле
при необходимости разверните их в несколько полей
поля являются результатом расширений слова - они составляют последнюю исполняемую команду
, за исключением «$ @»
, $ IFS
разделение полей и расширение имени пути входное слово всегда должно оцениваться как одно поле .
, а затем для выполнения полученной команды
Люди часто говорят, что оболочка представляет собой клей , и, если это правда, то это прикрепление списков аргументов - или полей - к тому или иному процессу, когда он exec
их. Большинство оболочек плохо обрабатывают байт NUL
- если вообще обрабатывают - и это потому, что они уже разбивают его. Оболочка должна exec
много , и она должна делать это с помощью массива аргументов с разделителями NUL
, которые она передает ядру системы во время exec
. . Если бы вы смешали разделитель оболочки с данными с разделителями, оболочка, вероятно, все испортила. Его внутренние структуры данных, как и большинство программ, полагаются на этот разделитель. В частности, zsh
не облажается.
И здесь на помощь приходит $ IFS
. $ IFS
- это всегда присутствующий, а также настраиваемый параметр оболочки, который определяет, как оболочка должна разделять расширения оболочки из слова . От до поля - конкретно, какие значения должны разделять эти поля . $ IFS
разделяет расширения оболочки по разделителям, отличным от NUL
- или, другими словами, оболочка заменяет байты, полученные в результате раскрытия, которые соответствуют значениям в значении $ IFS
] с NUL
во внутренних массивах данных. Если вы посмотрите на это так, вы можете начать видеть, что каждое расширение оболочки с разделением полей представляет собой массив данных с разделением на $ IFS
.
Важно понимать, что $ IFS
только ограничивает расширения, которые не уже иным образом ограничены - это можно сделать с помощью "
двойные кавычки. Когда вы цитируете расширение, вы ограничиваете его в начале и по крайней мере в конце его значения. В этих случаях $ IFS
не применяется, поскольку нет полей Фактически, расширение в двойных кавычках демонстрирует идентичное поведение разделения полей , чем раскрытие без кавычек, когда IFS =
имеет пустое значение.
Если не указано в кавычках, $ IFS
сам по себе является расширением оболочки с разделителями $ IFS
. По умолчанию используется указанное значение <пробел>
- все три из которых показывают специальные свойства, если они содержатся в $ IFS
. В то время как любое другое значение для $ IFS
указывается для оценки одного поля для каждого раскрытия вхождения ], $ IFS
пробел - любой из этих трех - указывается для исключения в одно поле для каждой последовательности расширения , а ведущие / замыкающие последовательности удаляются полностью. Это, вероятно, легче всего понять на примере.
slashes=///// spaces=' '
IFS=/; printf '<%s>' $slashes$spaces
<><><><><>< >
IFS=' '; printf '<%s>' $slashes$spaces
</////>
IFS=; printf '<%s>' $slashes$spaces
<///// >
unset IFS; printf '<%s>' "$slashes$spaces"
<///// >
Но это всего лишь $ IFS
- просто разделение слов или пробел , как просили, так что насчет специальных символов ?
Оболочка - по умолчанию - также расширяет некоторые маркеры без кавычек (например, ? * [
, как указано в другом месте здесь) в несколько полей , когда они встречаются в списке. Это называется раскрытием имени пути или подстановкой . Это невероятно полезный инструмент, и, поскольку это происходит после разделения полей в порядке синтаксического анализа оболочки, на него не влияют $ IFS - поля сгенерированные расширением имени пути ограничиваются в начале / конце самих имен файлов, независимо от того, содержат ли их содержимое какие-либо символы в настоящее время в $ IFS
. Это поведение включено по умолчанию, но в противном случае его очень легко настроить.
set -f
Это указывает оболочке , а не на glob . Расширение имени пути не произойдет, по крайней мере, до тех пор, пока этот параметр не будет каким-либо образом отменен - например, если текущая оболочка будет заменена другим новым процессом оболочки или ....
set +f
... будет передано оболочке. Двойные кавычки - как и для $ IFS
field-splitting - делают этот глобальный параметр ненужным для каждого раскрытия. Итак:
echo "*" *
... если расширение имени пути в настоящее время включено, вероятно, будет давать очень разные результаты для каждого аргумента - поскольку первый будет расширяться только до его буквального значения (единственный символ звездочки, то есть совсем не ) и второй, только если текущий рабочий каталог не содержит имен файлов, которые могли бы соответствовать (и он соответствует почти всем из них) . Однако, если вы сделаете:
set -f; echo "*" *
... результаты для обоих аргументов идентичны - *
в этом случае не расширяется.
Принимая во внимание все аспекты безопасности, упомянутые выше, и предполагая, что вы доверяете расширяемым переменным и контролируете их, можно использовать несколько путей с пробелами, используя eval
. Но будь осторожен!
$ FILES='"a b" c'
$ eval ls $FILES
ls: a b: No such file or directory
ls: c: No such file or directory
$ FILES='a\ b c'
$ eval ls $FILES
ls: a b: No such file or directory
ls: c: No such file or directory
Метод использования find directory -print0 | xargs -0
должен обрабатывать все спец. Однако для каждого файла/каталога требуется один PID, что может привести к проблемам с производительностью.
Позвольте мне описать другой метод надежной (и производительной )обработки файлов, с которым я недавно столкнулся, который подходит, если find
вывод должен обрабатываться после -как вкладка -разделенные данные CSV, например по АВК. При такой обработке нарушают работу только табуляции и символы новой строки в именах файлов :
Каталог сканируется через find directory -printf '%P\t///\n'
. Если путь не содержит табуляции или новой строки,это приводит к одной записи с двумя полями CSV :сам путь и поле, содержащее ///
.
Если в пути содержится вкладка, будет три поля :фрагмент пути1, фрагмент пути2 и поле, содержащее ///
.
Если есть новая строка, будет две записи :первая запись будет содержать фрагмент пути1, а вторая запись будет содержать фрагмент2 пути и поле, содержащее ///
.
Теперь ключевым фактом является то, что ///
не может естественным образом встречаться в путях. Также это своеобразный водонепроницаемый побег или терминатор.
Также можно написать программу (AWK ), которая просматривает find
вывод и, пока не найдет ///
, соединяет фрагменты вместе, зная, что новое поле это вкладка в пути, а новая запись - это новая строка в пути.
Вкладки можно безопасно экранировать как ///t
, а новые строки можно безопасно экранировать как ///n
, опять же, зная, что ///
не может естественным образом встречаться в путях к файлам. Преобразование ///t
и ///n
обратно во табуляцию и новую строку может произойти в конце, когда в результате обработки генерируется некоторый вывод.
Да, это звучит сложно, но разгадка в том, что нужны только два PID :экземпляр find
и awk
, которые выполняют описанный алгоритм. И это быстро.
Идея не моя, я нашел ее реализованной в этом новом (2019 )скрипте bash для синхронизации каталогов:Zaloha.sh . На самом деле у них есть документ, который описывает алгоритм.
Мне не удалось сломать/задушить эту программу специальными символами в именах файлов. Он даже правильно обрабатывал каталоги с названиями новой строки и табуляции...