Синтаксис Zsh несовместим с sh. Это достаточно близко, чтобы выглядеть как sh, но недостаточно близко, чтобы вы могли взять код sh и запустить его без изменений.
Если вы хотите запустить код sh в zsh, например, потому что у вас есть функция или фрагмент sh, написанный для sh, который вы хотите использовать в сценарии zsh, вы можете использовать встроенныйemulate
. Например, чтобы получить файл, написанный для sh, в сценарии zsh:
emulate sh -c 'source /path/to/file.sh'
Чтобы написать функцию или скрипт в синтаксисе sh и сделать возможным ее запуск в zsh, поместите это в начало:
emulate -L sh 2>/dev/null || true
В синтаксисе sh zsh поддерживает все конструкции POSIX (и примерно так же совместим с POSIX, как bash --posix
, ksh93 или mksh ). Он также поддерживает некоторые расширения ksh и bash, такие как массивы (0 -, проиндексированные в ksh, в bash и ниже emulate sh
, но 1 -, проиндексированные в родном zsh )и [[ … ]]
. Если вы хотите POSIX sh plus ksh globs, используйте emulate … ksh …
вместо emulate … sh …
и добавьте if [[ -n $BASH ]]; then shopt -s extglob; fi
ради bash (обратите внимание, что это не является локальным для скрипта/функции ).
Собственный способ zsh для перечисления всех записей в каталоге, кроме .
и ..
, это
set -- *(DN)
Здесь используются квалификаторы globD
для включения точечных файлов и N
для создания пустого списка при отсутствии совпадений.
Портативный способ sh для перечисления всех записей в каталоге, кроме .
и ..
, намного сложнее. Вам нужно перечислить точечные файлы, и если вы перечисляете файлы в текущем каталоге или по пути, который не обязательно будет абсолютным, вам нужно позаботиться о том, чтобы имя файла начиналось с тире. Вот один из способов сделать это, используя шаблоны ..?*.[!.]* *
для перечисления всех файлов, кроме .
и ..
, и удаляя нерасширенные шаблоны.
set --..?*
if [ "$#" -eq 1 ] && ! [ -e "$1" ] && ! [ -L "$1" ]; then shift; fi
set --.[!.]* "$@"
if [ "$#" -eq 1 ] && ! [ -e "$1" ] && ! [ -L "$1" ]; then shift; fi
set -- * "$@"
if [ "$#" -eq 1 ] && ! [ -e "$1" ] && ! [ -L "$1" ]; then shift; fi
Если все, что вы хотите сделать, это проверить, пуст ли каталог, есть гораздо более простой способ.
if ls -A /path/to/directory/ | grep -q '^'; then
echo "/path/to/directory is not empty"
else
echo "/path/to/directory is empty"
fi
Переменная MAILTO, если она установлена, извлекается из файла crontab, поэтому, если она существует и не является "", то она будет использоваться для всех последующих заданий в этом файле, точно так же, как если бы вы создали сценарий оболочки, подобный вашему второй пример. Поэтому достаточно установить его в начале файла crontab, точно так же, как вы можете изменить оболочку crontab с sh
на bash
с SHELL=/bin/bash
в начале файла согласно справочному файлу