Как сделать папку с помощью функции mkdir

How to Create Directories in Linux (mkdir Command)

21 Июня 2020
|

Терминал

В системах Linux вы можете создавать новые каталоги либо из командной строки, либо с помощью файлового менеджера вашего рабочего стола. Команда, которая позволяет вам создавать каталоги (также известные как папки) .

Синтаксис команды следующий:

Команда принимает одно или несколько имен каталогов в качестве аргументов

Чтобы создать каталог в Linux, передайте имя каталога в качестве аргумента команды. Например, чтобы создать новый каталог, вы должны выполнить следующую команду:

Вы можете проверить, что каталог был создан, перечислив содержимое с помощью команды :

При указании только имени каталога без полного пути оно создается в текущем рабочем каталоге.

Текущий рабочий каталог является каталогом , из которого вы работаете команды. Чтобы изменить текущий рабочий каталог, используйте команду.

Чтобы создать каталог в другом месте, вам нужно указать абсолютный или относительный путь к файлу родительского каталога. Например, чтобы создать новый каталог в каталоге, введите:

Если вы попытаетесь создать каталог в родительском каталоге, где у пользователя недостаточно прав, вы получите сообщение об ошибке:

Опция ( ) указывает напечатать сообщение для каждого созданного каталога.

Родительский каталог — это каталог, который находится над другим каталогом в дереве каталогов. Чтобы создать родительские каталоги, используйте опцию.

Допустим, вы хотите создать каталог :

Если какой-либо из родительских каталогов не существует, вы получите ошибку, как показано ниже:

Вместо того, чтобы создавать отсутствующие родительские каталоги один за другим, вызовите команду с опцией:

Когда опция используется, команда создает каталог, только если он не существует.

Если вы попытаетесь создать каталог, который уже существует, а опция не указана, выдается ошибка:

Чтобы создать каталог с конкретными разрешениями, используйте параметр ( ). Синтаксис для назначения разрешений такой же, как с командой.

В следующем примере мы создаем новый каталог с разрешениями, что означает, что только пользователь, создавший каталог, сможет получить к нему доступ:

Если опция не используется, вновь созданные каталоги обычно имеют либо или разрешения, в зависимости от значения.

Чтобы создать несколько каталогов, укажите имена каталогов в качестве аргументов команды через пробел:

Команда также позволяет создавать сложное дерево каталогов с помощью одной команды:

Команда выше создает следующее дерево каталогов :

Для получения дополнительной информации посетите страницу руководства mkdir .

Rationale

The mkdir() function originated in 4.2 BSD and was added to System V in Release 3.0.

4.3 BSD detects .

The POSIX.1-1990 standard required that the group ID of a newly created directory be set to the group ID of its parent directory or to the effective group
ID of the creating process. FIPS 151-2 required that implementations provide a way to have the group ID be set to the group ID of the containing directory, but
did not prohibit implementations also supporting a way to set the group ID to the effective group ID of the creating process. Conforming applications should
not assume which group ID will be used. If it matters, an application can use chown() to set the group ID after the directory is created, or determine
under what conditions the implementation will set the desired group ID.

Будни автоматизации или «мне нужна программка для 3D упаковки» Промо

Автоматизация отечественных предприятий, которой приходиться заниматься, это нужная и высокооплачиваемая, но довольно нервная работа. Выручает юмор. Например, при общении с требовательным клиентом можно вспомнить анекдот: «Держась руками за стену, на ногах еле стоит мужик. К нему пристает ребенок: «Ну, папа, пожалуйста, сделай мне кораблик!», папа отвечает: «Ага! — Сейчас все брошу и пойду делать тебе кораблик!». Про один такой сделанный для клиента «кораблик» и хочется рассказать. Надеюсь, совместное погружение в теплое ламповое (то есть клиентоориентированное) программирование доставит Вам положительные эмоции, да и задача попалась интересная. Поплыли?

Errors

The mkdir() function shall fail if:

EACCES
Search permission is denied on a component of the path prefix, or write permission is denied on the parent directory of the directory to be created.
EEXIST
The named file exists.
ELOOP
A loop exists in symbolic links encountered during resolution of the path argument.
EMLINK
The link count of the parent directory would exceed {LINK_MAX}.
ENAMETOOLONG
The length of the path argument exceeds {PATH_MAX} or a pathname component is longer than {NAME_MAX}.
ENOENT
A component of the path prefix specified by path does not name an existing directory or path is an empty string.
ENOSPC
The file system does not contain enough space to hold the contents of the new directory or to extend the parent directory of the new directory.
ENOTDIR
A component of the path prefix is not a directory.
EROFS
The parent directory resides on a read-only file system.

The mkdir() function may fail if:

ELOOP
More than {SYMLOOP_MAX} symbolic links were encountered during resolution of the path argument.
ENAMETOOLONG
As a result of encountering a symbolic link in resolution of the path argument, the length of the substituted pathname string exceeded
{PATH_MAX}.

The following sections are informative.

Команды для файлов

Далее приведены основные команды для осуществления взаимодействия с файлами. Начинающим полезно опробовать каждую из них, чтобы лучше понять принцип работы утилит.

Список основных команд

  • touch file — создать файл.
  • realpath file — узнать абсолютный путь к файлу.
  • stat file1 — получение информации о «file1» (размер файла, дата создания файла и т. д.) и проверка существования файла.
  • cat > file — запись в файл.
  • cat file — чтение файла.
  • echo текст >> file — дописать в файл текст.
  • find file — поиск файла.
  • mcedit file — редактирование файла (также можно использовать редакторы Nano, Vim и другие).
  • cat file1 file2 > file12 — объединение файлов.
  • sh filename — запустить файл со сценарием Bash.
  • ./filename — запустить исполняемый файл.
  • cp file1 file2 — копировать файл «file1» с переименованием на «file2». Произойдёт замена файлов, если элемент с таким же названием существует.
  • mv file1 file2 — переименовать файл «file1» в «file2».
  • mv filename dirname — переместить файл «filename» в каталог «dirname».
  • less filename — открыть файл в окне терминала.
  • file filename — определение типа файла.
  • head filename — вывод нескольких начальных строк из файла на экран (построчное чтение файла). По умолчанию строк 10.
  • tail filename — вывод нескольких конечных строк из файла на экран.
  • diff file1 file2 — сравнение файлов.
  • grep text filename — поиск и вывод строк из файла, содержащих «text».
  • rm filename — удалить файл.

Подробную информацию об утилитах можно получить, воспользовавшись справочной службой: «man <название утилиты>».

Захват целого файла

Теперь мы переходим к рассмотрению некоторых уникальных возможностей PHP для обработки файлов: обработка больших блоков данных в одной или двух строках. Например, как можно захватить файл и вывести все его содержимое на вашу Web-страницу? Что же, вы видели пример использования цикла с. Но как сделать это проще? Процесс почти смехотворно прост при использовании, которая помещает весь файл в строку.

1
2

Хотя это и не лучший вариант, вы можете записать эту команду еще короче:

1

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

1

Это команда фактически та же, что и:

1
2

Должно быть, вы смотрите на эти примеры и думаете, «Это все-таки слишком трудоемкий способ». PHP-разработчики согласны с вами. Поэтому вы можете сократить приведенную выше команду до:

1

Функцияпередает на вывод все содержимое файла или Web-страницы в выходной буфер по умолчанию. По умолчанию эта команда выводит сообщение об ошибке при сбое. Во избежание такого поведения (если вы этого хотите), попробуйте команду:

1

Конечно, если вам необходимо обрабатывать содержимое файлов, то одна строка, возвращаемая— это, пожалуй, слишком. Вы, возможно, захотите сначала разбить ее на части с помощью функции.

1

Но к чему вам все эти сложности, если есть идеально подходящая функция, которая сделает за вас эту работу? Функция PHPвыполняет эту задачу в один шаг: она возвращает строковый массив, элементами которого являются строки файла.

1

Следует заметить, что между двумя приведенными выше примерами есть небольшое отличие. Командаудаляет знаки перехода на новую строку, тогда как при использовании командыстроки массива оканчиваются знаками перехода на новую строку (также, как и при использовании).

Возможности PHP, тем не менее, далеко превосходят описанные выше. Вы можете разбить целые .ini-файлы в стиле PHP всего одной командой. Командаприменима к файлам, сходным с приведенным в Листинге 4.

Листинг 4. Пример файла .ini
1
2
3
4
5
6
7
8
9

Следующие команды представляют файл в виде массива, а затем выводят этот массив на печать:

1
2

В результате будут получены следующие выходные данные:

Листинг 5. Выходные данные
1
2
3
4
5
6
7
8

Конечно, вы можете заметить, что данная команда объединила разделы. Это действие по умолчанию, но вы легко можете произвести необходимую настройку, воспользовавшись вторым аргументом:, который является переменной логического типа (Boolean). Установите значениекак True (истина).

1
2

И ваши выходные данные будут иметь вид:

Листинг 6. Выходные данные
1
2
3
4
5
6
7
8
9
10
11
12
13
14

PHP помещает данные в легко разбиваемый для анализа многомерный массив.

Но это лишь верхушка айсберга, если говорить об обработке файлов в PHP. Более сложные функции, напримеримогут помочь вам с обработкой соответственно HTML- и XML-документов. Обратитесь к разделу, чтобы получить более подробную информацию о работе этих функций. Обе они стоят внимания, если вы будете работать с файлами указанных типов, но вместо рассмотрения всех возможных типов файлов, вы можете внимательно ознакомиться с содержанием данной статьи, где есть несколько неплохих общих правил по работе с функциями, описанными мной к настоящему моменту.

ВПР по нескольким условиям с использованием дополнительного столбца.

Задачу, рассмотренную в предыдущем примере, можно решить и другим способом – без использования формулы массива. Ведь работа с массивами многим представляется сложной и недоступной для понимания. Дополнительный столбец для поиска по нескольким условиям будет в определенном отношении более простым вариантом.

Итак, необходимо выбрать значение выручки за определенный месяц, год и по нужному магазину. В итоге имеем 3 условия отбора.

Сразу по трем столбцам функция ВПР искать не может. Поэтому нам нужно объединить их в один. И, поскольку поиск производится всегда в крайнем левом (первом) столбце, то нужно добавить его в нашу таблицу тоже слева.

Вставляем перед таблицей с данными дополнительный столбец A. Затем при помощи оператора & объединяем в нем содержимое B,C и D. Записываем в А7

и копируем в находящиеся ниже ячейки.

Формула поиска в D4 будет выглядеть:

В диапазон поиска включаем и наш дополнительный столбец. Критерий поиска – также объединение 3 значений. И извлекаем результат из 5 колонки.

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

Вид станет приятнее, а на результаты это никак не повлияет.

Как работает серверный вызов в 1С Промо

Клиент-серверная архитектура заложена в платформе изначально — со времен «1С:Предприятие 8.0». Однако при разработке на 8.0 и 8.1 о разделении кода на клиентскую и серверную часть можно было не заботиться, поскольку на клиенте (на толстом клиенте) был доступен тот же функционал, что и на сервере. Всё изменилось с выходом платформы «1С:Предприятие 8.2», когда появился тонкий клиент. Теперь на клиенте доступен один функционал, на сервере — другой. Клиент и сервер «общаются» между собой с помощью серверного вызова. Конечно, это усложнило процесс разработки, но с другой стороны – можно создавать более оптимальные (быстрые) решения, поскольку все сложные задачи выполняются на сервере.

Генерация имён файлов в Bash

Иногда пользователю приходится работать с несколькими файлами одновременно, например, при выполнении переноса документов в другой каталог. Это станет проблемой, если элементов десятки или сотни и среди них нужно отобрать определённые.

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

Итак, теперь остаётся разобраться с вопросом составления шаблонов. Сейчас будут приведены основные конструкции для осуществления генерации имён. Чаще всего для отбора файлов применяется символ: «*». В случае использования этого знака в чистом виде, Bash выберет все элементы в каталоге без исключений.

root@test:~# ls *
document1.docx document2.docx document3.txt file1.txt file2.docx file3.txt

Для примера, чтобы из этого каталога отобрать файлы: file1, file2, file3, следует воспользоваться шаблоном:

root@test:~# ls file* 
file1.txt file2.docx file3.txt

Символ звёздочки позволяет командному интерпретатору выделить все файлы, начинающиеся с «file». При этом последующая часть наименования будет проигнорирована.

Кроме того, сгенерировать имена можно, взяв за основу расширение файла. Например:

root@test:~# ls .txt*
document3.txt file1.txt file3.txt

Description

The mkdir() function shall create a new directory with name path. The file permission bits of the new directory shall be initialized from
mode. These file permission bits of the mode argument shall be modified by the process’ file creation mask.

When bits in mode other than the file permission bits are set, the meaning of these additional bits is implementation-defined.

The directory’s user ID shall be set to the process’ effective user ID. The directory’s group ID shall be set to the group ID of the parent directory or to
the effective group ID of the process. Implementations shall provide a way to initialize the directory’s group ID to the group ID of the parent directory.
Implementations may, but need not, provide an implementation-defined way to initialize the directory’s group ID to the effective group ID of the calling
process.

The newly created directory shall be an empty directory.

If path names a symbolic link, mkdir() shall fail and set errno to .

Upon successful completion, mkdir() shall mark for update the st_atime, st_ctime, and st_mtime fields of the directory. Also,
the st_ctime and st_mtime fields of the directory that contains the new entry shall be marked for update.

Удобство использования докблоков в IDE

Если вы разрабатываете open source проект, то конечно документирование публичного API с помощью докблоков необходимо. Это не только позволит вам сгенерировать готовую документацию, но также позволит использовать ваш код удобно другим разработчикам в своих IDE. Что касается вашего приватного кода для аутсорс проекта, то использование докблоков может показаться не очень уместным, тем не менее советую их использовать, это значительно ускорит вашу разработку.

Для примера возьмем самую популярную IDE для PHP — PhpStorm. Рассмотрим предыдущий пример поиска кроликов:

$rabbits = $search->findRabbitsInLocations('/Sherwood/');
foreach ($rabbits as $rabbit) {
    $rabbit->doSomething();
}

Что хранят в себе переменные и ? PhpStorm об этом ничего не знает. PHP — язык слабо типизированный, тип результата функции не задается жестко из ее описания (привет PHP7, где это будет реализовано). Поэтому вашей IDE нужно подсказать с помощью докблоков, как вести себя с тем или иным кодом. Вариантов есть несколько. Можно сделать так:

/** @var Rabbit $rabbit */
foreach ($rabbits as $rabbit) {
    $rabbit->doSomething();
}

Или добавить тег в метод :

/**
 * @return Rabbit[]
 */
public function findRabbitsInLocations($locations)
{
    // some operations here...
    return ;
}

Обратите внимание, что мы указали , а не. Квадратные скобки дают понять, что возвращается массив объектов класса , если квадратные скобки убрать, то это будет означать, что метод возвращает один экземпляр класса

Еще можно написать так , вертикальная палка означает «ИЛИ», в данном случае мы указываем, что метод вернет либо массив кроликов, либо .

Независимо от того, какой способ указания типа вы выбрали, PhpStorm теперь будет выдавать вам подсказки, когда вы напечатаете и подождете мгновение:

Так происходит потому, что PhpStorm знает, что в переменную возвращается массив объектов класса . Далее в цикле переменная получает один элемент массива, который является экземпляром класса и PhpStorm показывает вам доступные публичные методы из этого класса.

Таким образом, не отрываясь от клавиатуры, вы можете использовать классы с публичными методами, которые написали ваши коллеги. PhpStorm будет выдавать вам подсказки, и если метод назван понятно, вы сможете использовать его даже без чтения его исходного кода и документации.

Еще одна полезная фича докблоков в паре с PhpStorm — это предупреждения о неправильных входных параметрах. Допишем докблок для одного из методов класса :

/**
 * Run in metres
 *
 * @param int $metres Metres
 */
public function runInMetres($metres)
{
    // some operations here...
}

Тут мы указываем, что на вход должно приходить целое число (опять же, в PHP7 это возможно будет задать на уровне синтаксиса самого языка). Что будет, если мы передадим в этот метод массив?

PhpStorm выделит цветом и выдаст вам подсказку, что на вход ожидается , а вы передает . Удобно, правда? Так же подсказки будут выдаваться и на несоответствие классов, интерфейсов. Если ваш метод поддерживает несколько типов для входящих аргументов, то разделите их также через |. В данном примере, если метод также умеет обрабатывать массивы, то в докблок можно дописать и PhpStorm перестанет ругаться.

PhpStorm также умеет сам генерировать докблоки. Поставте курсор строкой выше на объявление функции, класса или переменной, наберите и нажмите , IDE сгенерит вам докблок по шаблону, по желанию можно подправить. Также генерацию докблоков можно запустить через Alt + Insert.

Перенаправление данных

Перенаправление ввода-вывода в файл осуществляется с помощью специальных знаков. Для вывода используются «>» и «>>», а для ввода — «<».

Пример вывода «ls» в файл, а не на экран:

root@test:~# ls > files.txt
root@test:~# cat files.txt
file1.cpp sample.txt

Новый файл создаётся автоматически. В случае существования элемента с таким же наименованием, произойдёт перезапись. Чтобы этого избежать, необходимо использовать «>>». Тогда данные будут дописываться в документ.

Пример ввода, при котором информация выносится из файла с помощью команды «sort»:

root@test:~# echo text > file.txt
root@test:~# sort < file.txt
text

ВПР по двум условиям при помощи формулы массива.

У нас есть таблица, в которой записана выручка по каждому магазину за день. Мы хотим быстро найти сумму продаж по конкретному магазину за определенный день.

Для этого в верхней части нашего листа запишем критерии поиска: дата и магазин. В ячейке B3 будем выводить сумму выручки.

Формула в B3 выглядит следующим образом:

Обратите внимание на фигурные скобки, которые означают, что это формула массива. То есть наша функция ВПР работает не с отдельными значениями, а разу с массивами данных

Разберем процесс подробно.

Мы ищем дату, записанную в ячейке B1. Но вот только разыскивать мы ее будем не в нашем исходном диапазоне данных, а в немного видоизмененном. Для этого используем условие

То есть, в том случае, если наименование магазина совпадает с критерием в ячейке B2, мы оставляем исходные значения из нашего диапазона. А если нет – заменяем их на пробелы. И так по каждой строке.

В результате получим вот такой виртуальный массив данных на основе нашей исходной таблицы:

Как видите, строки, в которых ранее был «Магазин 1», заменены на пустые. И теперь искать нужную дату мы будем только среди информации по «Магазин 2». И извлекать значения выручки из третьей колонки.

С такой работой функция ВПР вполне справится.

Такой ход стал возможен путем применения формулы массива

Поэтому обратите особое внимание: круглые скобки в формуле писать руками не нужно! В ячейке B3 вы записываете  формулу. И затем нажимаете комбинацию клавиш CTRL+Shift+Enter.  При этом Excel поймет, что вы хотите ввести формулу массива и сам подставит скобки

И затем нажимаете комбинацию клавиш CTRL+Shift+Enter.  При этом Excel поймет, что вы хотите ввести формулу массива и сам подставит скобки.

Таким образом, функция ВПР поиск по двум столбцам производит в 2 этапа: сначала мы очищаем диапазон данных от строк, не соответствующих одному из условий, при помощи функции ЕСЛИ и формулы массива. А затем уже в этой откорректированной информации производим обычный поиск по одному только второму критерию при помощи ВПР.

Чтобы упростить работу в будущем и застраховать себя от возможных ошибок при добавлении новой информации о продажах, мы рекомендуем использовать «умную» таблицу. Она автоматически подстроит свой размер с учетом добавленных строк, и никакие ссылки в формулах не нужно будет менять.

Вот как это будет выглядеть.

Недостатки пользовательских функций PHP

У пользовательских функций в PHP есть и ряд минусов:
1.Нельзя объявить локальные функции. Сделать это так, как в других языках программирования, не получится. Вы попросту не сможете создать функцию внутри другой функции, чтобы 1-я вложенная функция была видна лишь во 2-ой функции. В языке программирования PHP такая вложенная функция станет доступна полностью всей программе (скрипту), то есть попросту не будет локальной.

Давайте объясним это на примере:

<?php
function first_function() {
  echo "<h4>1-я пользовательская функция</h4>";
    function second_function() {
     echo "<h5>2-я пользовательская функция</h5>";
    }
}
first_function();
second_function();
?>

В данном примере мы получим следующий вывод:

1-я пользовательская функция
2-я пользовательская функция

Это значит, что программе доступны обе функции. Таким образом, 2-я функция локальной не является.

2.Следующий минус пользовательских PHP-функций связан с областью видимости функций. Но прежде давайте поясним, какие переменные у нас глобальные, а какие локальные.

К глобальным относят переменные, доступные всей программе, включая подпрограммы. К локальным — переменные, определённые внутри функции (подпрограммы). То есть они доступны лишь внутри функции, в которой определены.

Для языка PHP все переменные, которые объявлены и используются в функции, по умолчанию локальны для функции. Таким образом, у вас отсутствует возможность по умолчанию изменить значение глобальной переменной в теле функции.

Когда вы будете в теле пользовательской функции использовать переменную с именем, которое идентично имени глобальной переменной (находится вне пользовательской функции), то эта локальный переменная не будет иметь ни малейшего отношения к глобальной переменной. В такой ситуации в пользовательской функции создаётся локальная переменная с именем, которое идентично имени глобальной переменной, причем доступна эта локальная переменная будет лишь внутри данной пользовательской функции.

Вот как это выглядит на практике:

<?php
$a = 100;

function funct() {
$a = 70;
 echo "<h4>$a</h4>";
}
funct();
echo "<h2>$a</h2>";
?>

Сценарий выведет сначала 70, а потом 100:

70
100

Чтобы избавиться от вышеописанного недостатка, в PHP есть специальная инструкция global — она позволяет работать с глобальными переменными пользовательской функции.

Полезные функции

// Проверка файлов и директорий на существование
if( file_exists("file.txt") ){
  echo "Файл или директория существует";
}

// Проверка файлов на существование
if( is_file("file.txt") ){
 echo "Файл существует";
}

// Проверка директорий на существование
if( is_dir("images") ){
  echo "Директория существует";
}

// Размер файла
echo "Длина файла file.txt: " .filesize("file.txt");

// Время изменения и доступа к файлу
echo "Файл file.txt был изменён: " . filemtime("file.txt");
echo "и запрошен: " . fileatime("file.txt");

// Что можно с файлом делать?
if( is_readable("file.txt") ){
  echo "Файл можно читать";
}

if( is_writable("file.txt") ){
  echo "В файл можно писать";
}

if( is_executable("file.exe") ){
  echo "Файл можно исполнять";
}

Подведем итог

Сегодня мы впервые поговорили про функции в программировании и выяснили, чем они отличаются от функций в математике. Кроме того мы узнали, что в Питоне можно:

  • использовать готовые функции, которые уже встроены либо в базовый функционал, либо в дополнительную библиотеку;
  • объявлять собственные функции через ключевое слово def и название функции; а также
  • создавать анонимные или lambda-функции, которые очень удобно применять там, где в полноценных собственных функциях нет необходимости

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

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

Наконец, мы поговорили про возможность передачи различного количества позиционных и именованных аргументов через *args и **kwargs.

Вопросы для закрепления

Какие три вида функций мы изучили?

Посмотреть правильный ответ

Ответ: встроенные, собственные, а также анонимные или lambda-функции.

Какие бывают параметры и аргументы функции?

Посмотреть правильный ответ

Ответ: позиционные (в этом случае мы указываем только аргумент, но ставим его в определенном порядке) и именованные (указываем и параметр, и аргумент, но порядок не важен).

Какова область видимости локальной переменной?

Посмотреть правильный ответ

Ответ: область видимости локальной переменной ограничена той функцией, в которой эта переменная была объявлена.

В ноутбуке к лекции приведены ⧉.

В следующий раз мы подробнее рассмотрим списки, кортежи и множества.

Рейтинг
( Пока оценок нет )
Editor
Editor/ автор статьи

Давно интересуюсь темой. Мне нравится писать о том, в чём разбираюсь.

Понравилась статья? Поделиться с друзьями:
Люкс-хост
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: