Bash отключает историю в неинтерактивных оболочках по умолчанию, но можно включить его.
#!/bin/bash
HISTFILE=~/.bash_history
set -o history
history | tail …
Но при попытке контролировать действие по тому серверу, история оболочки бесполезна (это тривиально к командам выполнения, которые не обнаруживаются в истории). Посмотрите, Как я могу зарегистрировать все запуски процесса в Linux.
Если Вы отлаживаете сценарий, затем окружают историю, не лучший способ получить полезную информацию. Намного лучший инструмент является средством трассировки отладки: поместить set -x
около верхней части сценария. Трассировка записана в стандартную погрешность.
От удара человека
Расширение РАСШИРЕНИЯ выполняется на командной строке после того, как это было разделено на слова. Существует семь видов выполненного расширения: расширение фигурной скобки, расширение тильды, параметр и переменное расширение, управляет заменой, арифметическим расширением, разделением слова и расширением пути. Порядок расширений: расширение фигурной скобки, расширение тильды, параметр, переменная и арифметическая замена расширения и команды (выполненный слева направо вид), разделение слова и расширение пути.
array=( $names )
Причина это дает Вам 4 записи, состоит в том потому что неупомянутое $names
параметр далее подвергается разделению слова на основе внутреннего разделителя полей IFS
который является по умолчанию <space><tab><newline>
. Если необходимо было заключить в кавычки "$names"
для запрещения разделения слова затем Вы только получите один элемент массива со значением f 1 f 2
, снова не, что Вы хотите.
array=( * )
Вышеупомянутое, с другой стороны, только подвергается расширению пути, которое, оказывается, последнее выполненное расширение. Результаты не подвергаются слову, разделяющему таким образом, Вы получаете желаемые 2 элемента.
Если Вы хотите сделать array=( $names )
работайте затем, необходимо будет так или иначе разделить имена файлов непробелом, который также не содержится в именах файлов. Необходимо будет затем установить IFS на этот символ.
$ names=$(echo f* | sed "s/ /#/2")
$ echo $names
f 1#f 2
$ IFS='#' array=( $names )
$ echo ${#array[@]}
2
$ echo ${array[0]}
f 1
Более изящный способ сделать это должно было бы использовать байт NUL \0
как разделитель имени файла, поскольку это, как гарантируют, никогда не будет независимо имени файла. Для выполнения этого, мы должны будем использовать find
команда с -print0
флаг, а также read
встроенный разграниченный на NUL. Мы хорошо также должны очистить IFS, таким образом, никакое разделение слова на пробелах не выполняется.
#!/bin/bash
unset array
while IFS= read -r -d $'\0' name; do
array+=( "$name" )
done < <(find . -type f -name "f*" -print0 )
Расширение выполняется на командной строке после того, как это было разделено на слова.
Я вижу, как можно было бы быть смущен кавычкой выше только, чтобы иметь его, далее указывают, что разделение слова является 2-м для длительности расширения для появления.
Лучший путь к слову, которые заключают в кавычки, по-моему, был бы:
Расширение выполняется на командной строке после того, как это было разделено на аргументы.
Разделение аргументов на оболочке всегда делается пробелом, и именно те аргументы далее подвергаются расширению. Если Вы хотите иметь пробел в своем аргументе, необходимо или использовать Заключение в кавычки или Выход. IFS
не увеличивает разделение аргумента, только разделение слова.
Рассмотрите этот пример:
$ touch f{1,2}; IFS="#"; rm f1#f2
rm: cannot remove `f1#f2': No such file or directory
Заметьте как установка IFS
кому: #
не изменил то, что оболочка все еще только видела один аргумент f1#f2
; который между прочим затем далее подвергается различным расширениям.
Я настоятельно рекомендовал бы Вашу акватинту самостоятельно с BashFAQ, если Вы уже не имеете. В частности, я настоятельно рекомендовал бы, что Вы читаете следующие две дополнительных записи:
Команда оболочки (более точно, “простая команда”) состоит из списка слов. Каждое слово может быть произвольной строкой (слово оболочки может содержать пробелы и знаки пунктуации).
Когда Вы работаете echo -n *
, оболочка выполняет расширение пути (также названный поколением имени файла или globbing) на *
, и замены это списком соответствия именам файлов. Таким образом, после расширения, эта команда состоит из четырех слов: echo
, -n
, f 1
и f 2
. Команда echo
выполняется с двумя аргументами, и это печатает свои споры с промежуточным пространством (и никакая новая строка завершения из-за -n
опция). Таким образом, вывод f 1 f 2
. Осуществление: создайте другой файл, имя которого состоит из двух последовательных пробелов, выполненных echo -n *
, и удостоверьтесь, что Вы понимаете вывод.
Когда Вы работаете names=$(echo -n * )
, вывод от команды хранится в names
переменная. Здесь, та строка эквивалентна names='f 1 f 2'
.
Теперь мы добираемся до array=( $names )
. Это - присваивание массива, но оно не влияет на расширение в этом случае. С тех пор $names
неупомянутое переменное расширение, оно подвергается разделению слова, сопровождаемому расширением пути. Word, разделяющий средства, что значение переменной (который является строкой) разделяется на части в каждой пробельной последовательности (для точных правил, поиска IFS
в документации Вашей оболочки). Можно закончить с нулем, одним или несколькими словами; здесь строка разделяется на 4 слова: f
, 1
, f
и 2
. Таким образом, массив содержит четыре элемента (каждый слово с одним символом). Осуществление: с тем дополнительным файлом с двумя последовательными пробелами на его имя, каково теперь точное содержание массива?
Затем, Вы попробовали array=( * )
. Здесь, существует отдельное слово в массиве согласно обычным расширениям, последним из которых является расширение пути. С тех пор существует два файла соответствия, массив содержит два слова, названия каждого файла: f 1
и f 2
.
С точки зрения практики программирования оболочки, какой совет мы можем потянуть из этого анализа? Ну, во-первых, существует обычный принцип программирования оболочки: всегда помещайте двойные кавычки вокруг переменных расширений, если у Вас нет серьезного основания не к. Затем не храните список в строковой переменной. Если Вы хотите сохранить список имен файлов, поместите его непосредственно в массив:
files=(*)
ls -l "${files[@]}"
Дальнейшее осуществление: создайте файл, имя которого является единственной звездочкой (touch '*'
) и выполненный эти команды снова. Вы понимаете вывод?
В стороне: zsh не выполняет разделение слова или расширение пути на переменных расширениях. Это делает его вполне немного более нормальным к программе в.
#
как разделитель (который не будет работать, если имя файла будет содержать #
), Ваш ответ корректен. Но это не является очень дидактическим. В частности, Вы не объясняете, что команда не является строкой, а списком строк, который часто сбивает с толку для окружения новичков.
– Gilles 'SO- stop being evil'
12.03.2011, 03:09
#
пример, потому что я явно использовал его, чтобы быть дидактическим; намного легче визуализировать #
чем байт NUL. Я также сделал специальное замечание, что этот символ не должен иметь независимо имени файла и затем продолжил давать более надлежащее решение для байта NUL. С моей точки зрения Ваш ответ составлял 90%, то же и другие 10% будет более соответствующим как комментарий. Но, Вы не можете добраться до 21K для того, чтобы сделать только комментарии так C'est la vie.
– SiegeX
12.03.2011, 03:26
IFS
промежуточный: Вы получите различные разделения. (foo="one two three,four,,five"; echo $foo; IFS=,; echo $foo
)
– Gilles 'SO- stop being evil'
13.03.2011, 13:39
man bash
(10% до сих пор :). Теперь, об этой проблеме в частности. Я начинаю получать ощущение его, но если мой compehension не является путем прочь, выборка страницы справочника, которую Вы заключили в кавычки, говорит,"Expansion is performed on the command line after it has been split into words..."
и затем продолжает, который одно из "расширений"word splitting
. Это похоже на противоречие.. таким образом, это поднимает проблему "механизма" снова.. Я только что заметил, что Gilles отправил и упоминает что-то о "словах оболочки".. (но я должен пойти теперь... назад позже), – Peter.O 12.03.2011, 02:43