Советы по UNIX: Осваиваем 10 полезных приемов работы в UNIX

Откажитесь от неудачных приемов работы в UNIX

Освоив 10 полезных приемов, вы повысите эффективность работы с командной строкой UNIX и сможете избежать плохих моделей организации работы.

Майкл Штатц, автор, консультант

Фото Майкла ШтатцаМайкл Штатц (Michael Stutz) - автор Справочника по Linux (The Linux Cookbook) , который он разработал, используя только открытые программные средства. Он заинтересован в цифровой публикации книги и ее дальнейшем использовании. В течение 20 лет он использовал разные операционные системы UNIX. Вы можете найти Майкла на stutz@dsl.org.



18.04.2007

Введение

Часто используя какую-либо систему, мы привыкаем к некоторым шаблонам работы. Но не всегда эти шаблоны оказываются оптимальными. Иногда мы даже приобретаем плохие привычки, которые приводят к беспорядку и неуклюжести в работе. Один из наилучших путей исправления таких недостатков – выработка привычки использовать хорошие приемы, которые препятствуют беспорядку. Эта статья предлагает 10 методов работы с командной строкой UNIX, достойных стать привычками, которые помогут вам избежать много общих недостатков и повысить эффективность работы. Подробное описание каждого из методов приведено после списка.

Усвоим 10 хороших привычек

Десять хороших методов, к которым стоит привыкнуть:

  1. Создавайте деревья каталогов одной командой.
  2. Изменяйте пути; не переносите архив.
  3. Объединяйте ваши команды с операторами управления.
  4. Будьте внимательны при использовании кавычек в работе с переменными.
  5. Используйте управляющую последовательность символов для ввода длинной строки.
  6. Объединяйте команды в список.
  7. Используйте xargs для вывода find.
  8. Знайте, когда использовать grep для подсчета - а когда от него лучше отказаться.
  9. Сравнивайте определенные поля при выводе, не только строки.
  10. Не используйте передачу вывода cat.

Создавайте деревья каталогов одной командой

Листинг 1 иллюстрирует один из наиболее распространенных неудачных методов работы в UNIX: пошаговое определение дерева каталогов.

Листинг 1. Пример плохого метода работы #1: Пошаговое определение дерева каталогов
~ $ mkdir tmp
~ $ cd tmp
~/tmp $ mkdir a
~/tmp $ cd a
~/tmp/a $ mkdir b
~/tmp/a $ cd b
~/tmp/a/b/ $ mkdir c
~/tmp/a/b/ $ cd c
~/tmp/a/b/c $

Намного быстрее использовать опцию -p mkdir и создавать все родительские и дочерние каталоги одной командой. Но даже администраторы, которые знают об этой опции, до сих пор работают пошагово, создавая в командной строке каждый подкаталог в отдельности. Берегите свое время - привыкайте к хорошим методам:

Листинг 2. Пример хорошего метода работы #1: Определение дерева каталогов одной командой
~ $ mkdir -p tmp/a/b/c

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

Листинг 3. Еще один пример хорошего метода работы #1: Определение сложного дерева каталогов одной командой
~ $ mkdir -p project/{lib/ext,bin,src,doc/{html,info,pdf},demo/stat/a}

Раньше была только одна причина пошагово определять дерево каталогов - реализация mkdir не поддерживала эту опцию, но теперь это не актуально для большинства систем. IBM, AIX, mkdir, GNU mkdir и остальные системы, соответствующие единой спецификации UNIX, сейчас имеют эту опцию.

Для немногих систем, в которых отсутствует эта возможность, следует использовать скрипт mkdirhier (см. Ресурсы), который служит оболочкой для mkdir и выполняет ту же функцию.

~ $ mkdirhier project/{lib/ext,bin,src,doc/{html,info,pdf},demo/stat/a}

Изменяйте пути; не переносите архив

Еще один неудачный метод работы - это перемещение архивного файла .tar в определенный каталог, если вам захотелось извлечь архив именно в этот каталог. Вам не стоит так делать. Вы можете распаковать любой архивный файл .tar в любой каталог - для этого предназначена опция -C. Используйте опцию -C, чтобы указать каталог для распаковки:

Листинг 4: Пример хорошего метода работы #2: Использование опции -C для распаковки архивного файла .tar
~ $ tar xvf -C tmp/a/b/c newarc.tar.gz

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


Объединяйте ваши команды с операторами управления

Вы, вероятно, уже знаете, что в большинстве оболочек вы можете комбинировать команды в одной командной строке с помощью использования точки с запятой (;) между ними. Точка с запятой - это управляющий оператор оболочки, и хотя он предназначен, для того чтобы связывать множественные отдельные команды в единую командную строку, его применение не всегда возможно. Например, предположим, что вы используете точку с запятой для объединения двух команд, в которых выполнение второй команды всецело зависит от успешного окончания первой. Если первая команда не выполняется так, как вы ожидаете, вторая команда все же запускается - и терпит неудачу. Вместо этого, используйте более подходящий оператор управления (некоторые описаны в данной статье). Если ваша оболочка их поддерживает, к ним стоит привыкнуть.

Запуск команды только в том случае, если другая команда возвратила нулевое значение

Используйте оператор управления && для объединения двух команд таким образом, что вторая команда будет выполняться, только если первая возвратила нулевое значение. Другими словами, если первая команда выполняется успешно, вторая команда тоже запускается. Если первая команда не выполняется, то вторая команда не запускается совсем. Например:

Листинг 5. Пример хорошего метода работы #3: Объединяйте команды с операторами управления
~ $ cd tmp/a/b/c && tar xvf ~/archive.tar

В этом примере содержимое архива извлекается в каталог ~/tmp/a/b/c, если этот каталог существует. Если каталог не существует, команда tar не запустится и из архива ничего не будет извлечено.

Запуск команды только в том случае, если другая команда возвратила ненулевое значение

Точно так же оператор управления || разделяет две команды и запускает вторую команду, только если первая команда возвратила ненулевое значение. Другими словами, если первая команда была успешной, вторая команда не запустится. Если первая команда завершилась с ошибкой, то вторая запустится. Этот оператор часто применяется для тестирования с условием: существует ли заданный каталог, если нет, то он его создает:

Листинг 6. Еще один пример хорошего метода работы #3: Объединяйте команды с операторами управления
~ $ cd tmp/a/b/c || mkdir -p tmp/a/b/c

Также можно комбинировать операторы управления, описанные в этом разделе. Каждый из них относится к последней запускавшейся команде:

Листинг 7. Комбинированный пример хорошего метода работы #3: Объединение команд с операторами управления
~ $ cd tmp/a/b/c || mkdir -p tmp/a/b/c && tar xvf -C tmp/a/b/c ~/archive.tar

Будьте внимательны при использовании кавычек в работе с переменными

Всегда будьте осторожны с расширением оболочки и именами переменных. Вообще-то, это хорошая идея - брать обращения к переменным в двойные кавычки, только если нету особых причин не делать этого. Аналогично, если непосредственно за именем переменной следует буквенно-цифровой текст, имя переменной следует заключить в фигурные скобки ({}), чтобы отличать ее от окружающего текста. Иначе оболочка интерпретирует замыкающий текст как часть имени переменной - и наиболее вероятный результат - нулевой код возврата. В Листинге 8 приведены примеры вариантов использования кавычек с именами переменных и получаемые результаты.

Листинг 8. Пример хорошего метода работы #4: Использование (и не использование) кавычек в работе с переменными
~ $ ls tmp/
a b
~ $ VAR="tmp/*"
~ $ echo $VAR
tmp/a tmp/b
~ $ echo "$VAR"
tmp/*
~ $ echo $VARa

~ $ echo "$VARa"

~ $ echo "${VAR}a"
tmp/*a
~ $ echo ${VAR}a
tmp/a
~ $

Используйте управляющую последовательность символов для ввода длинной строки

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

Листинг 9. Пример хорошего метода работы #5: Использование обратного слэша в длинных строках
~ $ cd tmp/a/b/c || \
> mkdir -p tmp/a/b/c && \
> tar xvf -C tmp/a/b/c ~/archive.tar

В качестве альтернативы приведена еще одна конфигурация, которая также работает:

Листинг 10. Альтернативный пример хорошего метода работы #5: Использование обратного слэша в длинных строках
~ $ cd tmp/a/b/c \
>                 || \
> mkdir -p tmp/a/b/c \
>                    && \
> tar xvf -C tmp/a/b/c ~/archive.tar

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

Примечание: В большинстве оболочек, когда вы нажимаете стрелку вверх, вся мульти-строка изображается в виде единой длинной строки.


Объединяйте команды в список

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

Запуск списка команд в дополнительной оболочке

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

Листинг 11. Пример хорошего метода работы #6: Запуск списка команд в дополнительной оболочке
~ $ ( cd tmp/a/b/c/ || mkdir -p tmp/a/b/c && \
> VAR=$PWD; cd ~; tar xvf -C $VAR archive.tar ) \
> | mailx admin -S "Archive contents"

В этом примере содержимое архива извлекается в каталог tmp/a/b/c, в то время как вывод сгруппированных команд, включая список извлеченных файлов, отправляется по почте на адрес admin.

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

Запуск списка команд в текущей оболочке

Используйте фигурные скобки ({}) для заключения списка команд для запуска в текущей оболочке. Убедитесь, что вы добавили пробелы между скобками и командами, т.к. в противном случае оболочка может неправильно интерпретировать скобки.. Также убедитесь, что после последней команды в списке стоит точка с запятой (;), как в следующем примере:

Листинг 12. Еще один пример хорошего метода работы #6: Запуск списка команд в текущей оболочке
~ $ { cp ${VAR}a . && chown -R guest.guest a && \
> tar cvf newarchive.tar a; } | mailx admin -S "New archive"

Применяйте xargs к результатам работы поиска find

Используйте команду xargs в качестве фильтра для работы со списком файлов, полученным в результате выполнения поиска командой find. Обычно команда find выдает список файлов, соответствующий некоторому критерию. Этот список передается к xargs, которая выполняет другие операции, используя список файлов в качестве аргументов, как в следующем примере:

Листинг 13. Пример классического применения команды xargs
~ $ find some-file-criteria some-file-path | \
> xargs some-great-command-that-needs-filename-arguments

Тем не менее, не думайте, что xargs - это только дополнение к find; это один из тех инструментов, привыкнув к которому, хочешь работать с ним постоянно, например, в следующих случаях:

Передача списка с разделяющими пробелами

В этой простой иллюстрации xargs похож на фильтр, который берет на вход список (каждый элемент на отдельной строке) и ставит его элементы на одну строку, разделяя их пробелами:

Листинг 14. Пример результата работы команды xargs
~ $ xargsabcControl-D
a b c
~ $

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

Листинг 15. Пример использования команды xargs
~/tmp $ ls -1 | xargs
December_Report.pdf README a archive.tar mkdirhier.sh
~/tmp $ ls -1 | xargs file
December_Report.pdf: PDF document, version 1.3
README: ASCII text
a: directory
archive.tar: POSIX tar archive
mkdirhier.sh: Bourne shell script text executable
~/tmp $

Команда xargs полезна не только для передачи имен файлов. Используйте ее каждый раз, когда вам надо отфильтровать текст в одну строку:

Листинг 16. Пример хорошего метода работы #7: Использование инструмента xargs для фильтрации текста в одну строку
~/tmp $ ls -l | xargs
-rw-r--r-- 7 joe joe 12043 Jan 27 20:36 December_Report.pdf -rw-r--r-- 1 \
root root 238 Dec 03 08:19 README drwxr-xr-x 38 joe joe 354082 Nov 02 \
16:07 a -rw-r--r-- 3 joe joe 5096 Dec 14 14:26 archive.tar -rwxr-xr-x 1 \
joe joe 3239 Sep 30 12:40 mkdirhier.sh
~/tmp $

Будьте осторожны, используя xargs

Формально, бывают редкие случаи, когда использование xargs может вызвать затруднение. По умолчанию, символ конца файла - это нижнее подчеркивание (_); если этот символ был передан на вход, как единственный аргумент, все после него будет игнорироваться. Как меру предосторожности используйте флаг -e, который без аргументов отключает символ конца файла.


Знайте, когда использовать grep для подсчета - а когда от него лучше отказаться

Избегайте использовать после grep команду wc -l для подсчета количества полученных строк. Опция -c в grep позволяет подсчитать количество строк, которые соответствуют заданным шаблонам и в целом работает быстрее, чем комбинация "wc после grep", как в следующем примере:

Листинг 17. Пример хорошего метода работы #8: Подсчет числа строк с и без grep
~ $ time grep and tmp/a/longfile.txt | wc -l
2811

real    0m0.097s
user    0m0.006s
sys     0m0.032s
~ $ time grep -c and tmp/a/longfile.txt
2811

real    0m0.013s
user    0m0.006s
sys     0m0.005s
~ $

Опция -c является хорошим способом подсчета не только из-за фактора скорости. При использовании нескольких файлов grep с опцией -c возвращает отдельное значение для каждого файла, по одному на каждой строке, тогда как направление вывода в wc дает общий результат для всех файлов.

Однако, этот пример интересен не только с точки зрения быстродействия – он иллюстрирует еще одну распространенную ошибку. Этот метод подсчета предоставляет только количество строк, в которых найдены соответствия образцу - и хорошо, если это то, что вы ищете. Но в случаях, где строки могут иметь несколько совпадений с конкретным образцом, эти методы не дадут реального числа соответствий образцу. Для подсчета числа совпадений используйте wc. Для начала запустите команду grep с опцией -o, если ваша версия поддерживает это. Эта опция выводит только соответствие образцу, по одному на каждую строку, но не саму строку. Ее нельзя использовать вместе с опцией -c, поэтому используйте wc -l для подсчета числа строк, как в следующем примере:

Пример хорошего метода работы #8: Подсчет числа совпадений с образцом с grep
~ $ grep -o and tmp/a/longfile.txt | wc -l
3402
~ $

В этом случае обращение к wc работает немного быстрее, чем второй вызов grep с фиктивным образцом, позволяющим выполнить сравнение и подсчет каждой строки (как grep -c).


Сравнение определенных полей вывода, не только строк

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

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

Листинг 19. Пример плохого метода работы #9: Использование grep для поиска образца в определенных полях
~/tmp $ ls -l /tmp/a/b/c | grep Dec
-rw-r--r--  7 joe joe  12043 Jan 27 20:36 December_Report.pdf
-rw-r--r--  1 root root  238 Dec 03 08:19 README
-rw-r--r--  3 joe joe   5096 Dec 14 14:26 archive.tar
~/tmp $

В этом примере grep фильтрует строки и выводит все файлы, в имени или дате изменения которых содержится Dec. Поэтому такой файл, как December_Report.pdf, подходит, даже если он не был изменен с января. Это, возможно, не то, что вы хотите. Для поиска соответствия образцу в конкретном поле лучше использовать awk, в котором относительный оператор соответствует конкретному полю, как показано в следующем примере

Листинг 20. Пример хорошего метода работы #9: Использование awk для поиска образца в определенных полях
~/tmp $ ls -l | awk '$6 == "Dec"'
-rw-r--r--  3 joe joe   5096 Dec 14 14:26 archive.tar
-rw-r--r--  1 root root  238 Dec 03 08:19 README
~/tmp $

Более подробно об использовании awk можно прочитать в разделе Ресурсы.


Не используйте передачу вывода cat

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

Листинг 21. Пример хорошего метода работы #10: Использование grep с cat и без него.
~ $ time cat tmp/a/longfile.txt | grep and
2811

real    0m0.015s
user    0m0.003s
sys     0m0.013s
~ $ time grep and tmp/a/longfile.txt
2811

real    0m0.010s
user    0m0.006s
sys     0m0.004s
~ $

Эта ошибка допускается во многих случаях. Так как большинство инструментов получают стандартный ввод в виде аргумента, используя тире (-), даже аргумент для использования cat для разнообразия многочисленных файлов с stdin часто не действителен. На самом деле необходимо выполнить конкатенацию перед использованием cat с одной из его нескольких опций фильтрации.


Заключение: привыкайте к хорошему

Мы рассмотрели несколько методов работы в командной строке. Плохие привычки замедляют работу и часто приводят к непредвиденным ошибкам. Эта статья рассказывает о 10 новых способах, которые могут помочь вам избавиться от многих наиболее распространенных ошибок. Привыкайте к этим хорошим методам и улучшайте свои навыки работы с командной строкой Unix.

Ресурсы

Научиться

Получить продукты и технологии

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=AIX и UNIX
ArticleID=210485
ArticleTitle=Советы по UNIX: Осваиваем 10 полезных приемов работы в UNIX
publish-date=04182007