Как рекурсивно найти последний измененный файл в каталоге?
Кажется,ls
не сортирует файлы правильно при выполнении рекурсивного вызова:
ls -altR . | head -n 3
Как найти последний измененный файл в каталоге (включая подкаталоги)?
19 ответов
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "
для огромного дерева, это может быть трудно для sort
сохранить все в памяти.
%T@
дает вам время модификации, как метка времени unix,sort -n
сортировка численно, tail -1
занимает последнюю строку (самая высокая метка времени),cut -f2 -d" "
вырезает первое поле (временную метку) из вывода.
Edit: как -printf
, вероятно, только GNU, ajreals использование stat -c
слишком. Хотя можно сделать то же самое на BSD, варианты для форматирования отличается (-f "%m %N"
казалось бы)
и я пропустил часть множественного числа; если вы хотите больше, то the последний файл, просто увеличьте аргумент хвоста.
на @plundra это, вот версия BSD и OS X:
find . -type f -print0 | xargs -0 stat -f "%m %N" |
sort -rn | head -1 | cut -f2- -d" "
вместо сортировки результатов и сохранения только последних измененных, вы можете использовать awk для печати только одного с наибольшим временем модификации (во время unix):
find . -type f -printf "%T@%p" | awk '
{
if (>max) {
max=;
getline mostrecent
} else
getline
}
END{print mostrecent}' RS=''
Это должен быть более быстрый способ решить вашу проблему, если количество файлов достаточно велико.
я использовал символ NUL (т. е. "\0"), потому что теоретически имя файла может содержать любой символ (включая пробел и новую строку), но это.
Если у вас нет такой патологической имена файлов в вашей системе вы также можете использовать символ новой строки:
find . -type f -printf "%T@\n%p\n" | awk '
{
if (>max) {
max=;
getline mostrecent
} else
getline
}
END{print mostrecent}' RS='\n'
кроме того, это работает и в mawk.
мне не удалось найти последний измененный файл под Solaris 10. Там find
нет и stat
не имеется. Я обнаружил следующее решение, которое хорошо работает для меня:
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print ," ", }' | sort | tail -1
показать имя файла, а также использовать
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print ," ",," ", }' | sort | tail -1
объяснение
-
find . -type f
находит и перечисляет все файлы -
sed 's/.*/"&"/'
обертывает путь в кавычки для обработки пробельными символами -
xargs ls -E
отправляет указанный путь вls
на-E
опция гарантирует, что полная метка времени (формат год-месяц-день час-минуты-секунды-наносекунд) возвращается -
awk '{ print ," ", }'
извлекает только дату и время -
awk '{ print ," ",," ", }'
извлекает дату, время и имя файла -
sort
возвращает файлы, отсортированные по дате -
tail -1
возвращает только последний измененный файл
Это, кажется, работает нормально, даже с поддиректориями:
find . -type f | xargs ls -ltr | tail -n 1
в случае слишком большого количества файлов уточните поиск.
показывает последний файл с человеческой читаемой меткой времени:
find . -type f -printf '%TY-%Tm-%Td %TH:%TM: %Tz %p\n'| sort -n | tail -n1
результат выглядит так:
2015-10-06 11:30: +0200 ./foo/bar.txt
чтобы показать больше файлов, замените -n1
С большим номером
Это дает отсортированный список:
find . -type f -ls 2>/dev/null | sort -M -k8,10 | head -n5
измените порядок, поместив '- r' в команду сортировки. Если вам нужны только имена файлов, вставьте " awk "{print $11} | / "перед" / head"
на Ubuntu 13 следующее делает это, возможно, немного быстрее, так как он меняет сортировку и использует "голову" вместо "хвоста", уменьшая работу. Чтобы показать 11 новейших файлов в дереве:
найти . - введите f-printf '%T@ %p\n' / sort-n-r | head -11 | cut - f2- - d" " | sed-e 's,^./ ,, '/xargs ls-U-l
Это дает полный список ls без повторной сортировки и опускает раздражающее"./ 'that' find ' ставит на каждое имя файла.
или, как bash функция:
treecent () {
local numl
if [[ 0 -eq $# ]] ; then
numl=11 # Or whatever default you want.
else
numl=
fi
find . -type f -printf '%T@ %p\n' | sort -n -r | head -${numl} | cut -f2- -d" " | sed -e 's,^\./,,' | xargs ls -U -l
}
тем не менее, большая часть работы была выполнена оригинальным решением plundra. Спасибо plundra.
это рекурсивно изменяет время модификации всех каталогов в текущем каталоге на самый новый файл в каждом каталоге:
for dir in */; do find $dir -type f -printf '%T@ "%p"\n' | sort -n | tail -1 | cut -f2- -d" " | xargs -I {} touch -r {} $dir; done
этот простой cli также будет работать:
ls -1t | head -1
вы можете изменить -1 на количество файлов, которые вы хотите перечислить
я столкнулся с той же проблемой. Мне нужно найти самый последний файл рекурсивно. поиск занял около 50 минут.
вот небольшой скрипт, чтобы сделать это быстрее:
#!/bin/sh
CURRENT_DIR='.'
zob () {
FILE=$(ls -Art1 ${CURRENT_DIR} | tail -n 1)
if [ ! -f ${FILE} ]; then
CURRENT_DIR="${CURRENT_DIR}/${FILE}"
zob
fi
echo $FILE
exit
}
zob
это рекурсивная функция, которая получает самый последний измененный элемент каталога. Если этот элемент является каталогом, функция вызывается рекурсивно и выполняет поиск в этом каталоге и т. д.
Я использую что-то подобное все время, а также список top-k самых последних измененных файлов. Для больших деревьев каталогов это может быть намного быстрее, чтобы избежать сортировки. В случае только top-1 последний измененный файл:
find . -type f -printf '%T@ %p\n' | perl -ne '@a=split(/\s+/, $_, 2); ($t,$f)=@a if $a[0]>$t; print $f if eof()'
в каталоге, содержащем 1,7 миллиона файлов, я получаю самый последний в 3.4 s, ускорение 7,5 x против решения 25,5 s с помощью сортировки.
если работает stat
на каждом файле по отдельности, чтобы замедлить вы можете использовать xargs
чтобы немного ускорить события:
find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -n | tail -1 | cut -f2- -d" "
Я нашел команду выше полезной, но для моего случая мне нужно было увидеть дату и время файла, а также у меня была проблема с несколькими файлами, которые имеют пробелы в именах. Вот мое рабочее решение.
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l
Я написал пакет pypi/github для этого вопроса, потому что мне также нужно было решение.
https://github.com/bucknerns/logtail
установка:
pip install logtail
использование: хвосты изменили файлы
logtail <log dir> [<glob match: default=*.log>]
Usage2: открывает последний измененный файл в Редакторе
editlatest <log dir> [<glob match: default=*.log>]
игнорирование скрытых файлов-с хорошей и быстрой отметкой времени
обрабатывает пробелы в именах файлов хорошо - не то, что вы должны использовать их!
$ 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
Галор можно найти по ссылке.
Я нахожу следующее короче и с более интерпретируемым выходом:
find . -type f -printf '%TF %TT %p\n' | sort | tail -1
учитывая фиксированную длину стандартизированного формата ISO datetimes, лексикографическая сортировка прекрасна, и нам не нужна -n
опция сортировки.
Если вы хотите удалить метки времени снова, вы можете использовать:
find . -type f -printf '%TFT%TT %p\n' | sort | tail -1 | cut -f2- -d' '