- Lektsia - бесплатные рефераты, доклады, курсовые работы, контрольные и дипломы для студентов - https://lektsia.info -

Интерпретатор командного языка shell

Интерпретатор командного языка shell 1. Основные понятия языка shell 1. 1. Ввод-вывод
Три направления ввода-вывода являются выделенными - стандартный ввод, стандартный вывод и стандартный протокол. Как правило, команды берут исходные данные из стандартного ввода и помещают результаты в стандартный вывод. Стандартные ввод, вывод и протокол можно переназначить. Обозначение

служит для переназначения стандартного ввода (дескриптор файла 0), > для стандартного вывода (дескриптор файла 1);

ввод происходит со стандартного ввода, пока не встретится указанная или конец файла, >>

для стандартного вывода; если файл существует, то выводимая информация добавляется к конец этого файла,

в качестве стандартного ввода об(r)является файл, ассоциированный с дескриптором ; аналогично для стандартного вывода >& & закрывают соответственно стандартный ввод и вывод.

Если любой из этих конструкций предшествует цифра, то с указанным файлом будет ассоциирован дескриптор, равный указанной цифре, вместо 0 и 1 по умолчанию. Например, 2 > для стандартного протокола используется дескриптор 2, а 2 >& 1

ассоциирует дескриптор 2 с файлом, ассоциированным с дескриптором 1... .. 2>protocol
переназначает стандартный протокол (дескриптор 2) в файл по имени protocol. Чтобы переназначить стандартный протокол туда же, куда уже назначен стандартный вывод, следует употребить конструкцию .... 2>&1
Важен порядок переназначения: shell производит переназначение слева направо по указанному списку. Так, 1 > xxx 2 >& 1
сначала ассоциирует дескриптор 1 с файлом xxx, а затем дескриптор 2 с 1, т. е. тоже с xxx. А 2 >& 1 1 > xxx ассоциирует дескриптор 2 с терминалом, а 1 - с файлом xxx. Можно переназначить системный ввод на текущий файл: isql - - 1. 2. Синхронное и асинхронное выполнение команд
Обычно shell ждет завершения выполнения команды. Однако имеется возможность запустить задачу в асинхронном режиме, т. е. без ожидания ее завершения. Для этого после команды (после всех ее аргументов и указаний о переназначении ввода-вывода) надо поставить знак &. При этом по умолчанию стандартный ввод команды назначается на пустой файл /dev/null. Пример: создать файл primer можно по команде echo > primer
Еще пример: запустить программу prog в асинхронном режиме, чтобы не надо было дожидаться его завершения, засечь время выполнения, результаты программы направить в файл prog. res, данные о времени выполнения - в файл prog. tim. time prog > prog. res 2> prog. tim & 1. 3. Конвейер
Конвейер - последовательность команд, разделенных знаком |. Если после конвейера стоит ; shell ждет его завершения. Если & - то не ждет. Роль ; может играть конец строки. Смысл конвейера в том, что стандартный вывод одной команды замыкается на стандартный ввод другой. Пример конвейера - подсчитать число об(r)ектных файлов в текущем каталоге. ls *. o | wc -l 1. 4. Метасимволы, генерация имен файлов
Метасимволы - символы, имеющие специальное значение для интерпретатора : ? * ; & ( ) | ^

Однако каждый из этих символов может представлять самого себя, если перед ним стоит \. Все символы, заключенные между кавычками ' и ', представляют самих себя. Между двойными кавычками (") выполняются подстановки команд (см п. 2. 2) и параметров (см. п. 2. 3), а символы \, `, " и $ могут экранироваться предшествующим символом \. После всех подстановок в каждом слове команды ищутся символы *, ?, и [. Если находится хотя бы один из них, то это слово рассматривается как шаблон имен файлов и заменяется именами файлов, удовлетворяющих данному шаблону (в алфавитном порядке). Если ни одно имя файла не удовлетворяет шаблону, то он остается неизменным. Значения указанных символов: * любая строка, включая и пустую ? один любой символ [.... ]
любой из указанных между ними символов. Пара символов, разделенных знаком -, означает любой символ, который находится между ними, включая и их самих. Если первым символом после "[" идет "! ", то указанные символы не должны входить в имя файла 2. Синтаксис языка shell 2. 1. Комментарии Строки, начинающиеся с #, трактуются как комментарии. 2. 2. Подстановка результатов выполнения команд
Выражения можно заключать в обратные кавычки (`). Такие выражения вычисляются в месте использования. Они могут быть, например, частью строк. Пример. Пусть параметром макрокоманды является имя файла с расширением . for. Требуется удалить одноименный файл с расширением . err. name=`ena -n $1` rm -f ${name}. err Значение, полученное в результате выполнения команды ena -n $1
присваивается переменной name. Фигурные скобки использованы для выделения аргумента операции перехода от имени к значению. Без них . err приклеилась бы к имени. 2. 3. Переменные и подстановка их значений
Все переменные в языке shell - текстовые. Их имена должны начинаться с буквы и состоять из латинских букв, цифр и знака подчеркивания (_). Чтобы воспользоваться значением переменной, надо перед ней поставить символ $. Использование значения переменной называется подстановкой. Различается два класса переменных: позиционные и с именем. Позиционные переменные - это аргументы командных файлов, их именами служат цифры: $0 - имя команды, $1 - первый аргумент и т. д. Значения позиционным переменным могут быть присвоены и командой set (см. Специальные команды). Пример. После вызова программы на shellе, хранящейся в файле ficofl: ficofl -d / \*. for
значением $0 будет ficofl, $1 - -d, $2 - /, $3 - *. for, значения остальных позиционных переменных будут пустыми строками. Заметим, что если бы символ * при вызове ficofl не был экранирован, в качестве аргументов передались бы имена всех фортранных файлов текущей директории. Еще две переменные хранят командную строку за исключением имени команды: $@ эквивалентно $1 $2 .... , а $* - "$1 $2 .... ". Начальные значения переменным с именем могут быть установлены следующим образом: = [ = ] ....

Не может быть одновременно функции (см. Управляющие конструкции) и переменной с одинаковыми именами. Для подстановки значений переменных возможны также следующие конструкции: ${}

если значение определено, то оно подставляется. Скобки применяются лишь если за следует символ, который без скобок приклеится к имени. ${: -}

если определена и не является пустой строкой, то подставляется ее значение; иначе подставляется . ${: =}

если не определена или является пустой строкой, ей присваивается значение ; после этого подставляется ее значение. ${: ?}

если определена и не является пустой строкой, то подставляется ее значение; иначе на стандартный вывод выводится и выполнение shellа завершается. Если опущено, то выдается сообщение "parameter null or not set". ${: +}

если определена и не является пустой строкой, то подставляется ; иначе подставляется пустая строка. Пример: если переменная d не определена или является пустой строкой, то выполняется команда pwd echo ${d: -`pwd`}

Следующие переменные автоматически устанавливаются shell'ом: # количество позиционных параметров (десятичное) флаги, указанные при запуске shellа или командой set ?
десятичное значение, возвращенное предыдущей синхронно выполненной командой $ номер текущего процесса ! номер последнего асинхронного процесса @ эквивалентно $1 $2 $3 .... * эквивалентно "$1 $2 $3 .... "
Напомним: чтобы получить значения этих переменных, перед ними нужно поставить знак $. Пример: выдать номер текущего процесса: echo $$ 2. 4. Специальные переменные Shell'ом используются следующие специальные переменные: HOME
директория, в которую пользователь попадает при входе в систему или при выполнении команды cd без аргументов PATH
список полных имен каталогов, в которых ищется файл при указании его неполного имени. PS1 основная строка приглашения (по умолчанию $) PS2
дополнительная строка приглашения (по умолчанию >); в интерактивном режиме перед вводом команды shell'ом выводится основная строка приглашения. Если нажата клавиша new_line, но для завершения команды требуется дальнейший ввод, то выводится дополнительная строка приглашения IFS
последовательность символов, являющихся разделителями в командной строке (по умолчанию это , и ) 3. Управляющие конструкции

Простая команда - это последовательность слов, разделенная пробелами. Первое слово является именем команды, которая будет выполняться, а остальные будут переданы ей как аргументы. Имя команды передается ей как аргумент номер 0 (т. е. имя команды является значением $0). Значение, возвращаемое простой командой - это ее статус завершения, если она завершилась нормально, или (восьмеричное) 200+статус, если она завершилась аварийно. Список - это последовательность одного или нескольких конвейеров, разделенных символами ; , &, && или || и быть может заканчивающаяся символом ; или &. Из четырех указанных операций ; и & имеют равные приоритеты, меньшие, чем у && и ||. Приоритеты последних также равны между собой. Символ ; означает, что конвейеры будут выполняться последовательно, а & - параллельно. Операция && (||) означает, что список, следующий за ней будет выполняться лишь в том случае, если код завершения предыдущего конвейера нулевой (ненулевой). Команда - это либо простая команда, либо одна из управляющих конструкций. Кодом завершения команды является код завершения ее последней простой команды. 3. 1. Цикл ДЛЯ for [ in ] do done

Если часть in опущена, то это означает in "$@" ( то есть in $1 $2 .... $n). Пример. Вывести на экран все фортранные файлы текущей библиотеки: for f in *. for do cat $f done 3. 2. Оператор выбора case $ in | .... ) ; ; ... . esac

Оператор выбора выполняет , соответствующий первому , которому удовлетворяет . Форма шаблона та же, что и используемая для генерации имен файлов. Часть | шаблон.... может отсутствовать. Пример. Определить флаги и откомпилировать все указанные файлы. # инициализировать флаг flag= # повторять для каждого аргумента for a do case $a in # об(r)единить флаги, разделив их пробелами -[ocSO]) flag=$flag' ' $a ; ; -*) echo 'unknown flag $a' ; ; # компилировать каждый исходный файл и сбросить флаги *. c) cc $flag $a; flag= ; ; *. s) as $flag $a; flag= ; ; *. f) f77 $flag $a; flag= ; ; # неверный аргумент *) echo 'unexpected argument $a' ; ; esac done 3. 3. Условный оператор. if then [ elif then ] ... . [ else ] fi

Выполняется и, если код его завершения 0, то выполняется , иначе - и, если и его код завершения 0, то выполняется . Если же это не так, то выполняется . Части elif и else могут отсутствовать. 3. 4. Цикл ПОКА while do done

До тех пор, пока код завершения последней команды есть 0, выполняются команды . При замене служебного слова while на until условие выхода из цикла меняется на противоположное. В качестве одной из команд может быть команда true (false). По этой команде не выполняется никаких действий, а код завершения устанавливается 0 (-1). Эти команды применяются для организации бесконечных циклов. Выход из такого цикла можно осуществить лишь по команде break (см. Специальные команды). 3. 5. Функции () { ; }

Определяется функция с именем . Тело функции - , заключенный между { и }. 3. 6. Зарезервированные слова Следующие слова являются зарезервированными: if then else elif fi case in esac { } for while until do done 3. 7. Специальные команды

Как правило, для выполнения каждой команды shell порождает отдельный процесс. Специальные команды отличаются тем, что они встроены в shell и выполняются в рамках текущего процесса. : Пустая команда. Возвращает нулевой код завершения. . file
Shell читает и выполняет команды из файла file, затем завершается; при поиске file используется список поиска $PATH. break [n]
Выход из внутреннего for или while цикла; если указано n, то выход из n внутренних циклов. continue [n]
Перейти к следующей итерации внутреннего for или while цикла; если указано n, то переход к следующей итерации n-ого цикла. cd [ ]

Сменить текущую директорию на директорию . По умолчанию используется значение HOME. echo [ .... ]

Выводит свои аргументы в стандартный вывод, разделяя их пробелами. eval [ .... ]

Аргументы читаются, как если бы они поступали из стандартного ввода и рассматриваются как команды, которые тут же и выполняются. exec [ .... ]

Аргументы рассматриваются как команды shell'а и тут же выполняются, но при этом не создается нового процесса. В качестве аргументов могут быть указаны направления ввода-вывода и, если нет никаких других аргументов, то будет изменено лишь направление ввода-вывода текущей программы. exit [ n ]
Завершение выполнения shell'а с кодом завершения n. Если n опущено, то кодом завершения будет код завершения последней выполненной команды (конец файла также приводит к завершению выполнения). export [ .... ]

Данные переменные отмечаются для автоматического экспорта в окружение (см. Окружение) выполняемых команд. Если аргументы не указаны, то выводится список всех экспортируемых переменных. Имена функций не могут экспортироваться. hash [ -r ] [ .... ]

Для каждой из указанных команд определяется и запоминается путь поиска. Опция -r удаляет все запомненные данные. Если не указан ни один аргумент, то выводится информация о запомненных командах: hits - количество обращений shell'а к данной команде; cost - объем работы для обнаружения команды в списке поиска; command - полное имя команды. В некоторых ситуациях происходит перевычисление запомненных данных, что отмечается значком * в поле hits. pwd Выводит имя текущей директории. read [ .... ]

Читается из стандартного ввода одна строка; первое ее слово присваивается первой переменной, второе - второй и т. д. , причем все оставшиеся слова присваиваются последней переменной. readonly [ .... ]

Запрещается изменение значений указанных переменных. Если аргумент не указан , то выводится информация обо всех переменных типа readonly. return [ n ]
Выход из функции с кодом завершения n. Если n опущено, то кодом завершения будет код завершения последней выполненной команды. set [ --aefkntuvx [ .... ] ] Команда устанавливает следующие режимы: -a

отметить переменные, которые были изменены или созданы, как переменные окружения (см. Окружение) -e
если код завершения команды ненулевой, то немедленно завершить выполнение shell'а -f запретить генерацию имен файлов -k
все переменные с именем помещаются в окружение команды, а не только те, что предшествуют имени команды (см. Окружение) -n читать команды, но не выполнять их -t завершение shell'а после ввода и выполнения одной команды -u
при подстановке рассматривать неустановленные переменные как ошибки -v вывести вводимые строки сразу после их ввода -x вывести команды и их аргументы перед их выполнением -
не изменяет флаги, полезен для присваивания позиционным переменным новых значений.  
При указании + вместо - каждый из флагов устанавливает противоположный режим. Набор текущих флагов есть значение переменной $-. - это значения, которые будут присвоены позиционным переменным $1, $2 и т. д. Если все аргументы опущены, выводятся значения всех переменных. shift [ n ]

Позиционные переменные, начиная с $(n+1), переименовываются в $1 и т. д. По умолчанию n=1. test
вычисляет условные выражения (см. Дополнительные сведения. Test ) trap [ ] [ n ] ....

Команда будет выполнена, когда shell получит сигнал n (см. Сигналы). (Надо заметить, что проверяется при установке прерывания и при получении сигнала). Команды выполняются по порядку номеров сигналов. Любая попытка установить сигнал, игнорируемый данным процессом, не обрабатывается. Попытка прерывания по сигналу 11 (segmentation violation) приводит к ошибке. Если опущен, то все прерывания устанавливаются в их начальные значения. Если есть пустая строка, то этот сигнал игнорируется shell'ом и вызываемыми им программами. Если n=0, то выполняется при выходе из shell'а. Trap без аргументов выводит список команд, связанных с каждым сигналом. type [ .... ]

Для каждого имени показывает, как оно будет интерпретироваться при использовании в качестве имени команды: как внутренняя команда shell'а, как имя файла или же такого файла нет вообще. ulimit [ -f ] [ n ]
Устанавливает размер файла в n блоков; -f - устанавливает размер файла, который может быть записан процессом-потомком (читать можно любые файлы). Без аргументов - выводит текущий размер. umask [ nnn ]
Пользовательская маска создания файлов изменяется на nnn. Если nnn опущено, то выводится текущее значение маски. Пример: после команды umask 755 будут создаваться файлы, которые владелец сможет читать, писать и выполнять, а все остальные - только читать и выполнять. unset [ .... ]

Для каждого имени удаляет соответствующую переменную или функцию. Переменные PATH, PS1, PS2 и IFS не могут быть удалены. wait [ n ]
Ждет завершения указанного процесса и выводит код его завершения. Если n не указано, то ожидается завершения всех активных процессов-потомков и возвращается код завершения 0. 4. Выполнение shell-программ 4. 1. Запуск shell'а
Программа, интерпретирующая shell-программы, находится в файле /bin/sh. При запуске ее первый аргумент является именем shell-программы, остальные передаются как позициональные параметры. Если файл, содержащий shell-программу, имеет право выполнения (x), то достаточно указания лишь его имени. Например, следующие две команды операционной системы эквивалентны (если файл ficofl обладает указанным правом и на самом деле содержит shell-программу): sh ficofl -d . g\* и ficofl -d . g\* 4. 2. Выполнение
При выполнении shell-программ выполняются все подстановки. Если имя команды совпадает с именем специальной команды, то она выполнается в рамках текущего процесса. Так же выполняются и определенные пользователем функции. Если имя команды не совпадает ни с именем специальной команды, ни с именем функции, то порождается новый процесс и осуществляется попытка выполнить указанную команду. Переменная PATH определяет путь поиска директории, содержащей данную команду. По умолчанию это : :/bin: /usr/ bin: /util: /dss/rk
Директории поиска разделяются двоеточиями; : : означает текущую директорию. Если имя команды содержит символ /, значение $PATH не используется: имена, начинающиеся с / ищутся от корня, остальные - от текущей директории. Положение найденной команды запоминается shellом и может быть опрошено командой hash. 4. 3. Окружение
Окружение - это набор пар имя-значение, которые передаются выполняемой программе. Shell взаимодействует с окружением несколькими способами. При запуске shell создает переменную для каждой указанной пары, придавая ей соответствующее значение. Если вы измените значение какой-либо из этих переменных или создадите новую переменную, то это не окажет никакого влияния на окружение, если не будет использована команда export для связи переменной shell'а с окружением (см. также set -a). Переменная может быть удалена из окружения командой unset (см. ). Таким образом, окружение каждой из выполняемых shell'ом команд формируется из всех неизмененных пар имя-значение, первоначально полученных shell'ом, минус пары, удаленные командой unset, плюс все модифицированные и измененные пары, которые для этого должны быть указаны в команде export. Окружение простых команд может быть сформировано указанием перед ней одного или нескольких присваиваний переменным. Так, TERM=d460 и (export TERM; TERM=d460; )

эквивалентны. Переменные, участвующие в таких присваиваниях, назовем ключевыми параметрами. Если установлен флаг -k (см. set), то все ключевые параметры помещаются в окружение команды, даже если они записаны после команды. 4. 4. Сигналы UNIX'ом поддерживаются следующие сигналы: SIGHUP - 1 отменить (hangup) SIGINT - 2 прерывание (interrupt) SIGQUIT - 3 нестандартный выход (quit) SIGILL - 4 неверная команда (illegal instruction) SIGTRAP - 5 ловушка (trace trap) SIGFPE - 8
исключительная ситуация при выполнении операций с плавающей запятой (floating-point exception) SIGKILL - 9 уничтожение процесса (kill) SIGBUS - 10 ошибка шины (bus error) SIGSEGV - 11 нарушение сегментации (segmentation violation) SIGSYS - 12 неверный системный вызов (bad argument to system call) SIGPIPE - 13
запись в канал без чтения из него (write on a pipe with no one to read it) SIGALRM - 14 будильник (alarm clock) SIGTERM - 15
программное завершение процесса (software termination signal) Сигналы SIGINT и SIGQUIT игнорируются, если команда была запущена асинхронно. Иначе сигналы обрабатываются так же, как в процессе-предке, за исключением сигнала SIGSEGV (см. также Специальные команды. Trap). 4. 5. Замечания
При выполнении команд запоминается их местонахождение. Поэтому при создании команды с тем же именем, но находящейся в другой директории, все равно будет выполняться старая команда (если вызов происходит по короткому имени). Для исправления ситуации воспользуйтесь командой hash с ключом -r (см. Специальные команды). Если вы переименовали текущую или вышележащую директорию, то команда pwd может давать неверную информацию. Для исправления ситуации воспользуйтесь командой cd с полным именем директории. 5. Дополнительные сведения 5. 1. Команда test
Команда test применяется для проверки условия. Формат вызова: test или [ ]

Команда test вычисляет и, если его значение - истина, возвращает код завершения 0 (true); иначе - ненулевое значение (false). Ненулевой код завершения возвращается и если опущены аргументы. может состоять из следующих примитивов: -r файл - истина, если файл существует и доступен для чтения -w файл - истина, если файл существует и доступен для записи -x файл - истина, если файл существует и является выполняемым -f файл - истина, если файл существует и является обычным файлом -d файл - истина, если файл существует и является директорией -c файл

- истина, если файл существует и является специальным символьно-ориентированным файлом -b файл
- истина, если файл существует и является специальным блок-ориентированным файлом -p файл
- истина, если файл существует и является именованным каналом (pipe) -s файл - истина, если файл существует и имеет ненулевую длину -t [ дескриптор файла ]
- истина, если открытый файл с указанным дескриптором (по умолчанию 1) существует и ассоциирован с терминалом -z s1 - истина, если длина строки s1 нулевая -n s1 - истина, если длина строки s1 ненулевая s1 = s2 - истина, если строки s1 и s2 совпадают s1 ! = s2 - истина, если строки s1 и s2 не совпадают s1 - истина, если s1 непустая строка n1 -eq n2
- истина, если целые n1 и n2 алгебраически совпадают . На месте -eq могут быть также -ne, -gt, -ge, -lt, -le 5. 2. Команда expr
Команда expr применяется для вычисления выражений. Результат выводится на стандартный вывод. Операнды выражения должны быть разделены пробелами. Метасимволы должны быть экранированы. Надо заметить, что 0 возвращается в качестве числа, а не для индикации пустой строки. Строки, содержащие пробелы или другие специальные символы, должны быть заключены в кавычки. Целые рассматриваются как 32-битные числа. Ниже приведен список операторов в порядке возрастания приоритета, операции с равным приоритетом заключены в фигурные скобки. Перед символами, которые должны быть экранированы, стоит \. \|

если первое не пустое и не нулевое, то возвращает его, иначе возвращает второе \&

если оба не пустые и не нулевые, то возвращает первое , иначе возвращает 0 { =, \>, \>=, \

возвращает результат целочисленного сравнения если оба - целые; иначе возвращает результат лексического сравнения { +, - } сложение и вычитание целочисленных аргументов { \*, /, % }

умножение, деление и получение остатка от деления целочисленных аргументов :

оператор сопоставления : сопоставляет первый аргумент со вторым, который должен быть регулярным выражением. Обычно оператор сравнения возвращает число символов, удовлетворяющих образцу (0 при неудачном сравнении). Однако символы \( и \) могут применяться для выделения части первого аргумента. Регулярное выражение строится следующим образом: . - обозначает любой символ * - обозначает предыдущий символ, повторенный несколько раз []
- обозначают любой один из указанных между ними символов; группа символов может обозначаться с помощью знака "-" (т. е. [0-9] эквивалентно [0123456789]); если после [ стоит ^, то это эквивалентно любому символу, кроме указанных в скобках и ; для указания ] в качестве образца, надо поставить ее сразу за [ (т. е. [].... ]); . и * внутри квадратных скобок обозначают самих себя Все остальные символы (и ^, если стоит не в квадратных скобках) обозначают самих себя. Для указания символов . , *, [ и ] надо экранировать их (т. е. писать \. , \*, \[, \]). Примеры. 1. a=`expr $a + 1` - увеличение на 1 переменной a 2. expr $a : '. */\(. *\)' \| $a

- выделяет из имени файла короткое имя (т. е. из /usr/util/ena выделяется ena). Внимание, одиночный символ / будет воспринят как знак операции деления. 3. expr $VAR : '. *' - получение количества символов переменной VAR.
В качестве побочного эффекта expr возвращает следующие коды завершения: 0 - если выражение не нуль и не пустая строка 1 - если выражение нуль или пустая строка 2 - для некорректных выражений Команда expr также выдает следующие сообщения об ошибках: syntax error - для ошибок в операторах или операндах non-numeric argument
- для попыток применения арифметических операций к нечисловым строкам Замечание.
Допустим, что мы хотим сравнить значение переменной a с каким-либо символом, имеющим для expr особый смысл, например, со знаком равенства. Пусть $a на самом деле является знаком равенства. Так как аргументы предварительно обрабатываются shell'ом, то команда expr $a = '=' будет воспринята как expr = = =
что синтаксически некорректно. В подобных случаях надо пользоваться таким приемом: expr X$a = X=
т. е. добавлением некоторого символа к обеим строкам, что никак не влияет на результат сравнения, однако позволяет избежать синтаксической ошибки. 5. 3. Команда ena
Команда ena позволяет получить части полного имени файла. Первый аргумент - флаг, второй - имя файла. Команда различает следующие флаги: -n - имя файла без расширения -f - имя файла с расширением -e - расширение -d - имя директории -p
- если имя файла начинается с . или ... , то эти символы выделяются из имени Ниже приводится текст программы ena, хранящийся в /util/ena. # Get part of pathname case $1 in -n )
expr $2 : '. */\(. *\)[. ]. *' \| $2 : '\(. *\)[. ]. *' \| $2 ; ; -f ) expr $2 : '. */\(. *\)' \| $2 ; ; -e ) expr $2 : '. *\([. ][^. /]*\)' \| ' ' ; ; -d ) expr $2 : '\(. *\)/. *' \| $2 ; ; -p ) expr $2 : '\([. ]\)/. *' \| $2 : '\([. ][. ]\)/. *' \| ' ' ; ; * ) echo "error: unknown part of pathname $1" exit 2 ; ; esac