Функцию bash, чтобы найти новые сопоставления с шаблоном файл



в Bash я хотел бы создать функцию, которая возвращает имя файла самого нового файла, который соответствует определенному шаблону. Например, у меня есть каталог файлов, таких как:



Directory/
a1.1_5_1
a1.2_1_4
b2.1_0
b2.2_3_4
b2.3_2_0


Я хочу самый новый файл, который начинается с 'b2'. Как мне это сделать в bash? Мне нужно иметь это в моем ~/.bash_profile сценарий.

453   6  

6 ответов:

The параметр -t Сортировать по времени. Затем вы можете захватить первый (самый новый) с head -1.

ls -t b2* | head -1

но будьте осторожны: почему вы не должны анализировать вывод ls

мое личное мнение: парсинг ls опасно только тогда, когда имена файлов могут содержать забавные символы, такие как пробелы или символы новой строки. Если вы можете гарантировать, что имена файлов не будут содержать забавных символов, то разбор ls вполне безопасный.

если вы разрабатываете скрипт, который предназначен для запуска многими людьми на многих системах во многих различных ситуациях, то я очень рекомендую не разбирать ls.

вот как это сделать "правильно":как я могу найти последний (самый новый, самый ранний, самый старый) файл в каталоге?

unset -v latest
for file in "$dir"/*; do
  [[ $file -nt $latest ]] && latest=$file
done

сочетание find и ls хорошо работает для

  • имена файлов без новых строк
  • не очень большое количество файлов
  • не очень длинные имена

решение:

find . -name "my-pattern" ... -print0 |
    xargs -0 ls -1 -t |
    head -1

давайте разберем его:

С find мы можем сопоставить все интересные файлы следующим образом:

find . -name "my-pattern" ...

затем с помощью -print0 мы можем передать все имена файлов благополучно к ls такой:

find . -name "my-pattern" ... -print0 | xargs -0 ls -1 -t

ls -t сортирует файлы по времени модификации (самый новый первый) и печатает его по одному в строке. Вы можете использовать -c Сортировать по времени создания. Примечание: это приведет к разрыву с именами файлов, содержащих новые строки.

наконец-то head -1 получает первый файл в отсортированном списке.

Примечание:xargs использовать системные ограничения на размер списка аргументов. Если этот размер превышает xargs будет звоните ls несколько раз. Это нарушит сортировку и, вероятно, также конечный результат. Беги

xargs  --show-limits

чтобы проверить ограничения на вашу систему.

примечание 2: использовать find . -maxdepth 1 -name "my-pattern" -print0 если вы не хотите искать файлы по подпапкам.

это возможная реализация требуемой функции Bash:

# Print the newest file, if any, matching the given pattern
# Example usage:
#   newest_matching_file 'b2*'
# WARNING: Files whose names begin with a dot will not be checked
function newest_matching_file
{
    # Use ${1-} instead of  in case 'nounset' is set
    local -r glob_pattern=${1-}

    if (( $# != 1 )) ; then
        echo 'usage: newest_matching_file GLOB_PATTERN' >&2
        return 1
    fi

    # To avoid printing garbage if no files match the pattern, set
    # 'nullglob' if necessary
    local -i need_to_unset_nullglob=0
    if [[ ":$BASHOPTS:" != *:nullglob:* ]] ; then
        shopt -s nullglob
        need_to_unset_nullglob=1
    fi

    newest_file=
    for file in $glob_pattern ; do
        [[ -z $newest_file || $file -nt $newest_file ]] \
            && newest_file=$file
    done

    # To avoid unexpected behaviour elsewhere, unset nullglob if it was
    # set by this function
    (( need_to_unset_nullglob )) && shopt -u nullglob

    # Use printf instead of echo in case the file name begins with '-'
    [[ -n $newest_file ]] && printf '%s\n' "$newest_file"

    return 0
}

Он использует только встроенные bash и должен обрабатывать файлы, имена которых содержат новые строки или другие необычные символы.

необычные имена файлов (например, файл, содержащий действительные \n характер может нанести ущерб с такого рода разбора. Вот способ сделать это в Perl:

perl -le '@sorted = map {$_->[0]} 
                    sort {$a->[1] <=> $b->[1]} 
                    map {[$_, -M $_]} 
                    @ARGV;
          print $sorted[0]
' b2*

Это преобразование Шварца используется там.

есть гораздо более эффективный способ достижения этой цели. Рассмотрим следующую команду:

find . -cmin 1 -name "b2*"

эта команда находит последний файл, созданный ровно минуту назад с помощью подстановочного знака поиска на "b2*". Если вы хотите файлы из последних двух дней, то вам будет лучше использовать следующую команду:

find . -mtime 2 -name "b2*"

The"."представляет текущий каталог. Надеюсь, это поможет.

можно использовать stat с файловым глобусом и украшением-сортировкой-undecorate с добавлением времени файла на передней панели:

$ stat -f "%m%t%N" b2* | sort -rn | head -1 | cut -f2-

Comments

    Ничего не найдено.