Вы правы насчет вывода type
и which
: поэтому их не следует использовать. Вы должны использовать command
.
pathx()
for cmd
do set "" "${PATH:?is NULL!}:"
while "${2:+set}" -- "${2%%:*}" "${2#*:}" 2>&3
do command -v -- "${1:-.}/$cmd"
done; done 3>/dev/null
Эта команда выполняет только command -v $PATH_component/$cmd
и поэтому она никогда не будет перечислять псевдонимы или встроенные модули или что-либо еще - она будет рекурсивно искать каждый компонент своей переменной окружения $PATH
для каждого из своих аргументов и выводить на stdout все, что найдет.
Если вы добавите && break
после command -v ...
она прервет поиск $PATH
в первый раз, когда успешно найдет $PATH
'd исполняемый файл с именем одного из аргументов.
Это была идея Майкла Хомера - и она действительно лучшая.
Он работает путем вложения цикла while
в цикл for
. для
каждой итерации цикла for
цикл while
перебирает все компоненты в $PATH
, проверяя кратчайший
отделенную двоеточием строку, которую он может нарезать ${2%%:*}
с помощью command -v $slice/$cmd
и сохранить самую длинную строку для следующей итерации ${2#*:}
. Только когда $PATH
полностью проверен, цикл while
пытается выполнить строку "${2:-NUL}"
и терпит неудачу, он завершается и начинается следующая итерация for
.
cp /bin/cat /tmp
(PATH=$PATH:/tmp pathx cat dd dummy doesntexist read echo)
/usr/bin/cat
/tmp/cat
/usr/bin/dd
/usr/bin/echo
Очевидно, вам действительно нужны псевдонимы
и прочее. Ну, это выполнимо:
shellx()
for cmd
do "set" -- "$cmd";"unset" cmd
for type in alias exe
do case $type in
(a*) "alias" "${1%%*=*}" ;;
(e*) PATH= "command" -v -- "$1" &&
type=function::builtin ||
"command" -v -- "$1" ;;
esac >&2&& "command" -V -- "$1" >&3 &&
cmd=$("command" -v -- "$1") && return
done;done 3>&2 2>/dev/null
Это было сложнее, чем я помню, но эта программа завершается, как только один из ее аргументов оказывается исполняемым. Он помещает его тип - один из alias, function::builtin, или exe в $type
, а команда идет в $cmd
. Псевдонимы получают определение, записанное в $cmd
- что в zsh
, bash
и yash
выглядит как...
alias x='something or other'
... в ksh93
это просто...
something or other
...и в dash
это...
x='something or other'
... но, опять же, все они получают переменную $type
assigned.
Если вы передадите ему аргумент, который является псевдонимом оболочки и каким-то образом был определен, хотя его имя содержит =
, то, ну, это не найдет его. Если вам нужна эта функциональность, то вам нужно будет потрошить вывод alias
, а не проверять его возврат.
Если исполняемый файл найден, вывод command -V
записывается в стандартную ошибку непосредственно перед возвратом функции. Она возвращает false, если исполняемый файл не найден.
Достаточно просто, учитывая, что вы пометили linux , у вас есть доступная команда stat
, которая извлекает время модификации файла, и команда GNU date
, которая извлекает час из определенное время:
find. -type f -exec sh -c '
h=$(date -d @$(stat -c %Y "$1") +%-H); [ "$h" -ge 11 ] && [ "$h" -lt 15 ]' \
sh {} \; -ls
Если результаты выглядят правильно, то:
find. -type f -exec sh -c '
h=$(date -d @$(stat -c %Y "$1") +%-H); [ "$h" -ge 11 ] && [ "$h" -lt 15 ]' \
sh {} \; -delete
Вот тестовый -запуск версии -ls
:
$ touch -d 'Wed Sep 12 11:00:01 EDT 2018' 11am
$ touch -d 'Wed Sep 12 12:00:02 EDT 2018' 12pm
$ touch -d 'Wed Sep 12 15:00:03 EDT 2018' 303pm
$ find. -type f -exec sh -c 'h=$(date -d @$(stat -c %Y "$1") +%-H); [ "$h" -ge 11 ] && [ "$h" -lt 15 ]' sh {} \; -ls
1705096 0 -rw-r--r-- 1 user group 0 Sep 12 2018./11am
1705097 0 -rw-r--r-- 1 user group 0 Sep 12 2018./12pm
Спасибо Кусалананде за написание отличного ответа, которому я следовал, в:Понимание опции -exec для `find`
Обратите внимание, что нам не нужна {} +
версия find
здесь, так как мы хотим, чтобы результаты -exec
относились к -файлу, чтобы мы удаляли только те файлы, которые соответствуют диапазон времени.
Сценарий встроенной оболочки состоит из двух основных частей :определения временной метки файла «час», а затем возврата успеха или неудачи в зависимости от диапазона. Первая часть сама состоит из двух частей. Переменной присваивается результат подстановки команды; команда должна быть прочитана внутри -снаружи:
$(stat -c %Y "$1")
--эта (вторая )команда -замена вызываетstat
параметр $1
встроенного сценария оболочки; $1
был назначен find
как один из найденных путей. Опция %Y команды stat
возвращает время модификации в секундах -с -эпохи -. date -d @... +%-H
--это берет секунды -с -эпохи -из приведенной выше подстановки команд и запрашивает date
дать нам часть часов этого времени; синтаксис@
говорит date
, что мы даем ему секунды -с -эпохи -в качестве входного формата. С опцией -
в формате вывода даты,мы указываем дате GNU , а не дополнять значение любыми ведущими нулями. Это предотвращает любую восьмеричную неправильную интерпретацию позже. Как только мы присвоим переменной $h
Hour, мы используем условный оператор bash [[
, чтобы узнать, больше ли это значение -чем -или -равно 11, а также строго меньше 15.
Не идеально, но может быть полезно.
find. -type f -print | while read l; do
hour=$(stat -c "%z" ${l} | awk '{print $2}' | awk -F: '{print $1}')
if [[ 11 -le ${hour} ]] && [[ ${hour} -le 15 ]]; do
rm -f ${l}
done
done