Я второй рекомендация Stevens. Единственная реальная альтернатива является Усовершенствованным Программированием UNIX M.J. Rochkind: http://basepath.com/aup/
Руководство Программиста POSIX РТОВ (http://oreilly.com/catalog/9780937175736) может быть полезным, но я не считал его сам.
Для наблюдения списка вот, два варианта, тот, который рекурсивно вызывает в подкаталоги и тот, который не делает. Весь синтаксис использования, характерный для удара, ksh и zsh.
comm -3 <(cd source && find -type f | sed 's/\.[^.]*$//' | sort) \
<(cd dest && find -type f | sed 's/\.[^.]*$//' | sort)
comm -3 <(cd source && for x in *; do printf '%s\n' "${x%.*}"; done | sort) \
<(cd dest && for x in *; do printf '%s\n' "${x%.*}"; done | sort)
Короче, в zsh:
comm -3 <(cd source && print -lr **/*(:r)) <(cd dest && print -lr **/*(:r))
comm -3 <(print -lr source/*(:t:r)) <(print -lr dest/*(:t:r))
comm
списки команд строки, которые характерны для двух файлов (comm -12
), это находится только в первом файле (comm -23
) или это находится только во втором файле (comm -13
). Числа указывают на то, что вычтено из вывода ¹. Два входных файла должны быть отсортированы.
Здесь, файлы являются на самом деле выводом команды. Оболочка оценивает <(…)
конструкция путем обеспечения “поддельного” файла (FIFO или a /dev/fd/
названный дескриптор файла) как аргумент команде.
¹ Так здесь минус sayers полностью выравниваются по ширине.
Если Вы захотите выполнить действия с файлами, то Вы, вероятно, захотите выполнить итерации по исходным файлам.
cd source
for x in *; do
set -- "…/dest/${x%.*}".*
if [ $# -eq 1 ] && ! [ -e "$1" ]; then
echo "$x has not been converted"
elif [ $# -gt 1 ]; then
echo "$x has been converted to more than one output file: " "$@"
else
echo "$x has been converted to $1"
fi
done