Как удалить файлы, созданные между двумя ранами?

Вы правы насчет вывода 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, если исполняемый файл не найден.

4
12.09.2018, 16:33
2 ответа

Достаточно просто, учитывая, что вы пометили , у вас есть доступная команда 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относились к -файлу, чтобы мы удаляли только те файлы, которые соответствуют диапазон времени.

Сценарий встроенной оболочки состоит из двух основных частей :определения временной метки файла «час», а затем возврата успеха или неудачи в зависимости от диапазона. Первая часть сама состоит из двух частей. Переменной присваивается результат подстановки команды; команда должна быть прочитана внутри -снаружи:

  1. $(stat -c %Y "$1")--эта (вторая )команда -замена вызываетstatпараметр $1встроенного сценария оболочки; $1был назначен findкак один из найденных путей. Опция %Y команды statвозвращает время модификации в секундах -с -эпохи -.
  2. date -d @... +%-H--это берет секунды -с -эпохи -из приведенной выше подстановки команд и запрашивает dateдать нам часть часов этого времени; синтаксис@говорит date, что мы даем ему секунды -с -эпохи -в качестве входного формата. С опцией -в формате вывода даты,мы указываем дате GNU , а не дополнять значение любыми ведущими нулями. Это предотвращает любую восьмеричную неправильную интерпретацию позже.

Как только мы присвоим переменной $hHour, мы используем условный оператор bash [[, чтобы узнать, больше ли это значение -чем -или -равно 11, а также строго меньше 15.

5
27.01.2020, 20:53

Не идеально, но может быть полезно.

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
0
27.01.2020, 20:53

Теги

Похожие вопросы