Вы можете сделать это с помощью встроенных функций (при условии, что вы используете GNU make):
VER=1.2.3
MINORVERTMP=$(subst.,,${VER})
MINORVER=$(word 1,${MINORVERTMP}).$(word 2,${MINORVERTMP})
all:
@echo ${MINORVER}
Если вы можете использоватьbmake
(BSD make ), у вас может быть больше (и, возможно, более простые )возможности:
VER=1.2.3
all: test1 test2
test1:
# simple regular expression-based replace like sed
@echo $@: ${VER:C,([^\.]*)\.([^\.]*).*,\1.\2,}
test2:
# replace all dot to spaces (S),
# print first and second element (:[1..2])
# with dot separator (ts.)
@echo $@: ${VER:S,.,,g:[1..2]:ts.}
С zsh
и GNUls
:
files=(*(NDoN:P))
(($#files)) && ls -ltd -- ${(u)files}
Или с анонимной функцией для краткости:
(){ (($#)) && ls -ltd -- ${(u)@}; } *(NDoN:P)
где N
позволяет nullglob
,D
dotglob
включать скрытые файлы, oN
пропускает сортировку, так как ls
сортирует по mtime, а :P
выполняет эквивалент GNU readlink -f
. Флаг расширения параметра (u)
удаляет дубликаты в массиве.
Или, если в текущем каталоге так много файлов, что описанное выше не удается с ошибкой слишком много аргументов , вы можете заставить zsh
выполнить сортировку и передать список вls -U
(в отключить собственную сортировку, требуется GNU ls
или совместимый )через zargs
, который, как и xargs
, при необходимости разбивает список на более мелкие фрагменты.
autoload zargs
files=(*(ND-om:P))
zargs -r --eof= -- ${(u)files} '' ls -lUd --
Где -om
сортирует по времени модификации после разрешения символической ссылки.
(beware zsh
's :P
в настоящее время подавляет символические ссылки, которые имеют бесконечные циклы в своем разрешении ).
С помощью bash
и инструментов GNU вы можете сделать что-то похожее на:
shopt -s nullglob dotglob
files=(*)
((${#files[@]})) &&
printf '%s\0' "${files[@]}" | # prints as NUL-delimited records
xargs -r0 readlink -zf -- | # get absolute canonical path
LC_ALL=C sort -zu | # removes duplicates
xargs -r0 stat --printf '%.9Y/%n\0' -- | # get mtime with max precision
sort -rnz | # sort numerically in reverse
cut -zd/ -f2- | # remove timestamp added earlier
xargs -r0 ls -lUd -- # pass to as many ls invocations as needed
При достаточно небольших списках файлов его можно упростить до:
shopt -s nullglob dotglob
files=(*)
((${#files[@]})) &&
readlink -zf -- "${files[@]}" | # get absolute canonical path
LC_ALL=C sort -zu | # removes duplicates
xargs -r0 ls -ltd -- # pass to ls
Посмотрите, как мы всегда передаем список файлов между инструментами в виде записей с разделителями NUL -. NUL — это единственный символ (и значение байта ), которые не могут встречаться в пути к файлу, поэтому это единственный безопасный метод.
В readlink -f * | sort
вы передаете список файлов из readlink
в sort
как записи, разделенные символом новой строки -, поэтому имена файлов, содержащие символы новой строки, будут нарушены. Поскольку вы забыли --
перед *
, это также сломает имена файлов, начинающиеся с -
.
Это намного хуже в ls -alt `cmd`
, где на этот раз вывод cmd
разделен на пробел, табуляцию и новую строку (, предполагая значение по умолчанию $IFS
), и генерация имени файла выполняется на результирующих словах, так что он подавился бы еще большим количеством символов. Без -d
,ls
также перечисляет содержимое каталогов, которые он передает в качестве аргументов, а не только сами каталоги.