Найти файлы в порядке временной метки

Найти файлы в порядке временной метки

dirимеет два обычных файла.

file1имеет abc\n, file2имеет def\n. Сожмите эти два файла с помощью gzip, как показано ниже,

#ls
#echo 'abc\n' > file1
#echo 'def\n' > file2
#gzip file1
#gzip file2
#ls
file1.gz  file2.gz

После того, как я прочитаю содержимое,

#find . -type f  -name "*.gz" -exec zgrep -Iq . \{} \; -exec zcat \{} \;
def\n
abc\n

Я не получаю содержимое файлов в порядке времени создания файла. Ожидаемый вывод должен быть всегда abc\ndef\n.

Интересное наблюдение: фактический результат иногда, def\nabc\nа иногдаabc\ndef\n

Вопрос:

Как найти файлы в порядке (убывания/возрастания) временной метки?

решение1

Порядок файлов, сообщаемых , findнепрозрачен для пользователя. Это может быть порядок, в котором они появляются в каталоге. Некоторые findреализации переупорядочивают их по номеру inode или другим критериям в попытке улучшить производительность. Единственный способ изменить порядок — через предикат, -depthкоторый сообщает findобрабатывать/выводить листья до ветви, на которой они находятся.

В качестве альтернативы findможно использовать zshрекурсивную функцию glob:

zgrep whatever ./**/*.gz(D.Om)

Квалификатор Omglob используется для сортировки по времени последнего изменения (сначала самые старые). .предназначен только для обычных файлов (эквивалент find's -type f), Dвключает скрытые (с точкой), как и findпо умолчанию.

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

autoload -U zargs # best in ~/.zshrc
zargs ./**/*.gz(D.Om) -- zgrep whatever

С помощью bash(или любой оболочки, поддерживающей подстановку процессов в стиле Ksh) и последних инструментов GNU эквивалент будет таким:

xargs -r0a <(
  export LC_ALL=C
  find . -type f -name '*.gz' -printf '%T@\t%p\0' |
    sort -zn | cut -zf2-) zgrep whatever

решение2

Один из вариантов — вывести временную метку файла вместе с путем к файлу, отсортировать по ней, а затем удалить ее:

find -type f -name "*.gz" -printf '%C@\t%p\n'|sort -nk1|cut -f2-|xargs zcat 

Обратите внимание: если имена ваших файлов могут содержать потенциально небезопасные символы (например, пробелы), просто замените

xargs zcat 

с

xargs -d "\n" zcat 

и если вам нужно учесть новые строки в именах файлов, вы можете использовать нулевой байт для завершения записей, как подробно описано в ответе @stéphane-chazelas (хотя на практике это редко вызывает проблемы).

решение3

К сожалению, команда find работает таким образом, что вывод не гарантирует, что он будет в алфавитном порядке или в порядке возраста файла. Вы можете попробовать что-то вроде:

ls -1dtr $(find . -maxdepth 1 -type f -name '*.gz') | xargs gzcat $1

Связанный контент