Как вывести список файлов, отсортированных по дате изменения рекурсивно (команда stat недоступна!)

31

Как я могу получить список всех файлов в текущем каталоге вместе с датой их изменения и отсортировать по этой дате?

Теперь я знаю, как этого добиться find, statи sort, но по какой-то странной причине statон не установлен на коробке, и вряд ли я смогу его установить.

Любой другой вариант?

PS: gccтоже не установлен

Алекс
источник
Можете ли вы загрузить скомпилированный бинарный файл и запустить его там?
imz - Иван Захарьящев
@imz: да, это еще один путь. find -printfДействие , кажется, самый простой , хотя.
Алекс

Ответы:

27

Мой самый короткий метод использует zsh:

print -rl -- **/*(.Om)

(добавьте Dквалификаторы glob, если вы также хотите перечислить скрытые файлы или файлы в скрытых каталогах).

Если у вас есть GNU find, заставьте его распечатать время изменения файла и отсортировать по нему. Я предполагаю, что в именах файлов нет новых строк.

find . -type f -printf '%T@ %p\n' | sort -k 1 -n | sed 's/^[^ ]* //'

Если у вас есть Perl (опять же, при условии отсутствия новых строк в именах файлов):

find . -type f -print |
perl -l -ne '
    $_{$_} = -M;  # store file age (mtime - now)
    END {
        $,="\n";
        print sort {$_{$b} <=> $_{$a}} keys %_;  # print by decreasing age
    }'

Если у вас есть Python (опять же, при условии отсутствия новых строк в именах файлов):

find . -type f -print |
python -c 'import os, sys; times = {}
for f in sys.stdin.readlines(): f = f[0:-1]; times[f] = os.stat(f).st_mtime
for f in sorted(times.iterkeys(), key=lambda f:times[f]): print f'

Если у вас есть SSH-доступ к этому серверу, смонтируйте каталог через sshfs на лучше оборудованной машине:

mkdir mnt
sshfs server:/path/to/directory mnt
zsh -c 'cd mnt && print -rl **/*(.Om)'
fusermount -u mnt

Только с инструментами POSIX это намного сложнее, потому что нет хорошего способа найти время модификации файла. Единственный стандартный способ получить время файла - lsвыходной формат зависит от локали и его сложно проанализировать.

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

set -ef                       # disable globbing
IFS='
'                             # split $(foo) only at newlines
set -- $(find . -type f)      # set positional arguments to the file names
mkdir links.tmp
cd links.tmp
i=0 list=
for f; do                     # hard link the files to links.tmp/0, links.tmp/1, …
  ln "../$f" $i
  i=$(($i+1))
done
set +f
for f in $(ls -t [0-9]*); do  # for each file, in reverse mtime order:
  eval 'list="${'$i'}         # prepend the file name to $list
$list"'
done
printf %s "$list"             # print the output
rm -f [0-9]*                  # clean up
cd ..
rmdir links.tmp
Жиль "ТАК - прекрати быть злым"
источник
Самый простой способ, наверное find . -print | xargs -n99999 -s999999 ls -ltr. Но в этом есть проблема, заключающаяся в том, что (1) xargsможет не разрешать -mбольше 512 или -sбольше 5120, и (b), даже если вы можете обойти это, все еще существует максимальный размер, наложенный ядром, для комбинированного списка аргументов и среды. Большинство ваших идей (кроме Perl и Python) имеют одну и ту же проблему, поэтому я специально избегал создания длинных командных строк.
geekosaur
В частности, я регулярно получаю ошибки «список аргументов слишком длинный» с использованием zshрекурсивных глобусов в общем случае.
geekosaur
@geekosaur: только последний ужасный кладж имеет проблему с длинными командными строками. В zsh вы можете многое сделать со встроенными модулями (например print -rl **/*, единственным ограничением является количество свободной памяти), и помимо этого zargs. Ваше предложение find … | xargs … lsбудет отсортировано правильно, если xargsвызов будет выполнен lsтолько один раз, и не будет работать, если в именах файлов есть специальные символы.
Жиль "ТАК - перестань быть злым"
большое спасибо за чрезвычайно подробный ответ с большим количеством вариантов! :)
alex
И именно поэтому я люблю Zsh.
Profpatsch
14

Предполагая, что GNU find:

find . -printf '%T@ %c %p\n' | sort -k 1n,1 -k 7 | cut -d' ' -f2-

Измените 1n,1на, 1nr,1если хотите, чтобы файлы, перечисленные в списке самых последних, были первыми

Если у вас нет GNU, findэто становится более сложным, поскольку lsформат меток времени сильно варьируется (например, недавно измененные файлы имеют другой стиль меток времени).

geekosaur
источник
На самом деле вы также можете изменить формат даты и времени с помощью ls --time-style="..."- я не уверен, является ли это стандартным или GNU ls, скорее всего, GNU.
asoundmove
Определенно GNU.
geekosaur
@asoundmove: к сожалению, коробка слишком старая (RedHat 7.2) и lsне имеет этой опции.
Алекс
7

На Mac нет аргумента -printf для поиска, но вы можете сделать это вместо этого:

find . -print0 | xargs -0 -n 100 stat -f"%m %Sm %N" | sort -n|awk '{$1="";print}'

killdash9
источник
0

это можно попробовать (хотя самому нужно создать) https://github.com/shadkam/recentmost

user3392225
источник
6
Добро пожаловать в Unix и Linux Stack Exchange! Хотя это может теоретически ответить на вопрос, было бы предпочтительным включить здесь основные части ответа и предоставить ссылку для справки.
SLM
0

Игнорирование скрытых файлов - с хорошей и быстрой отметкой времени

Хорошо обрабатывает пробелы в именах файлов - не то чтобы вы их использовали!

$ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |sort -nr |head -n 10

2017.01.25 18h23 Wed ./indenting/Shifting blocks visually.mht
2016.12.11 12h33 Sun ./tabs/Converting tabs to spaces.mht
2016.12.02 01h46 Fri ./advocacy/2016.Vim or Emacs - Which text editor do you prefer?.mht
2016.11.09 17h05 Wed ./Word count - Vim Tips Wiki.mht

Больше в findизобилии можно найти, перейдя по ссылке.

Серж Строобандт
источник
0

Говоря в общем о поиске файлов по дате (это не сработает для оригинального постера, но я попал сюда, так что я подумал, что другие тоже могут). В моем случае я хочу перечислить файлы с целью их просмотра перед удалением.

С findutils 4.6.0 мне нравится:

find . -type f -mtime +270 -exec ls -laFGht --time-style=iso {} \+

Приведенная выше команда находит файлы ( -type f) в текущем рабочем каталоге ( .), которые были изменены более 270 дней назад ( -mtime +270также -mtime 0выдаст последние 24 часа и -mtime -5покажет последние 5 дней). Затем он использует lsдля их перечисления по дате, сначала самое новое ( -exec ls -laFGht --time-style=iso {} \+)

Вот пример вывода:

-rwxrwx---+ 1 user1 208M 2018-07-16  ./filename.bak*
-rwxrwx---+ 1 user1  702 2018-07-15  ./filename.ldf*
-rwxrwx---+ 1 user1 208M 2018-07-15  ./filename.bak*

Самое замечательное в этом то, что после того, как список был просмотрен, заменить часть списка на findкоманду delete просто:

find . -type f -mtime +270 -delete
Стеф
источник