В оболочке, как я могу tail
последний файл, созданный в каталоге?
linux
shell
shell-script
Итай Моав -Малимовка
источник
источник
Ответы:
Вы не разобрать вывод Ls! Парсинг вывода ls сложен и ненадежен .
Если вы должны сделать это, я рекомендую использовать find. Первоначально у меня был простой пример, чтобы дать вам суть решения, но так как этот ответ кажется довольно популярным, я решил пересмотреть его, чтобы предоставить версию, которую можно безопасно копировать / вставлять и использовать со всеми входными данными. Вы сидите удобно? Мы начнем с oneliner, который даст вам последний файл в текущем каталоге:
Не совсем ли это сейчас, не так ли? Здесь это снова как функция оболочки и отформатировано для более легкого чтения:
А теперь это как вкладчик:
Если все остальное не помогло, вы можете включить вышеуказанную функцию в свою
.bashrc
и считать проблему решенной с одним предупреждением. Если вы просто хотели выполнить работу, вам не нужно читать дальше.Предостережение в том, что имя файла, оканчивающееся одним или несколькими символами новой строки, все равно не будет
tail
правильно передано . Обойти эту проблему сложно, и я считаю достаточным, чтобы при обнаружении такого злонамеренного имени файла возникало относительно безопасное поведение при обнаружении ошибки «Нет такого файла» вместо чего-либо более опасного.Сочные детали
Для любопытных это утомительное объяснение того, как это работает, почему это безопасно и почему другие методы, вероятно, нет.
Опасность, Уилл Робинсон
Прежде всего, единственный байт, который является безопасным для разделения путей к файлам, является нулевым, потому что это единственный байт, универсально запрещенный в путях к файлам в системах Unix. При обработке любого списка путей к файлам важно использовать только нулевое значение в качестве разделителя и при передаче даже одного пути к файлу от одной программы к другой делать это таким образом, чтобы не задушить произвольные байты. Существует много, казалось бы, правильных способов решения этой и других проблем, которые терпят неудачу, предполагая (даже случайно), что в именах файлов не будет ни новых строк, ни пробелов. Ни одно предположение не является безопасным.
Для сегодняшних целей первый шаг - получить список файлов с нулевым разделением. Это довольно легко, если у вас есть
find
поддержка,-print0
такая как GNU:Но этот список еще не говорит нам, какой из них является новейшим, поэтому нам нужно включить эту информацию. Я решил использовать
-printf
переключатель поиска, который позволяет мне указать, какие данные появляются в выводе. Не все версииfind
поддержки-printf
(это не стандарт), но GNU find делает. Если вы окажетесь без-printf
вас, вам нужно будет полагаться,-exec stat {} \;
в какой момент вы должны отказаться от всякой надежды на переносимость, что такжеstat
не является стандартным. Сейчас я собираюсь перейти к предположению, что у вас есть инструменты GNU.Здесь я запрашиваю формат printf,
%T@
который представляет собой время изменения в секундах с начала эпохи Unix, за которым следует точка, а затем число, указывающее доли секунды. Я добавляю к этому еще один период и затем%p
(который является полным путем к файлу), прежде чем заканчивать нулевым байтом.Теперь у меня есть
Это может быть само собой разумеющимся, но ради полноты не
-maxdepth 1
позволяетfind
перечислять содержимое подкаталогов и\! -type d
пропускает каталоги, которые вы вряд ли захотитеtail
. Пока у меня есть файлы в текущем каталоге с информацией о времени модификации, так что теперь мне нужно отсортировать по времени модификации.Получая это в правильном порядке
По умолчанию
sort
ожидается, что его входные данные будут разделены символами новой строки. Если у вас есть GNU,sort
вы можете попросить его ожидать записи с нулевым разделителем, используя-z
переключатель .; для стандартаsort
нет решения. Меня интересует только сортировка по первым двум числам (секундам и долям секунды), и я не хочу сортировать по фактическому имени файла, поэтому я говорюsort
две вещи: во-первых, он должен рассматривать period (.
) как разделитель полей и второе, что оно должно использовать только первое и второе поля при рассмотрении того, как сортировать записи.Прежде всего, я объединяю три коротких варианта, которые не имеют никакой ценности;
-znr
это просто краткий способ сказать-z -n -r
). После этого-t .
(пробел необязательный) сообщаетсяsort
символ разделителя полей и-k 1,2
указываются номера полей: первое и второе (sort
отсчитывает поля от одного, а не от нуля). Помните, что пример записи для текущего каталога будет выглядеть так:Это значит
sort
сначала посмотрим1000000000
а потом0000000000
при заказе этой записи.-n
Опция указываетsort
использовать численное сравнение при сопоставлении этих значений, поскольку оба значения числа. Это может быть не важно, поскольку числа имеют фиксированную длину, но это не вредит.Другой переключатель дано
sort
это-r
для «обратного». По умолчанию выходные данные числовой сортировки будут сначала с наименьшими числами,-r
изменяя их так, что они будут перечислять наименьшие последние номера и наибольшие первые числа. Поскольку эти числа являются метками времени выше, это будет означать более новые, и это помещает новейшую запись в начало списка.Просто важные биты
Поскольку список путей к файлам вытекает из
sort
него, теперь он имеет желаемый ответ, который мы ищем прямо вверху. Осталось найти способ отбросить другие записи и убрать метку времени. К сожалению, даже GNUhead
иtail
не принимают переключатели, чтобы заставить их работать на вводе с нулевым разделением. Вместо этого я использую цикл while как вид бедного человекаhead
.Сначала я сбрасываю,
IFS
чтобы список файлов не подвергался разбиению по словам. Далее я расскажуread
две вещи: не интерпретируйте escape-последовательности в input (-r
), а вход ограничивается нулевым byte (-d
); здесь пустая строка''
используется для обозначения «без разделителя», то есть с нулевым разделителем. Каждая запись будет считываться в переменную,record
поэтому при каждойwhile
итерации цикла у нее будет одна временная метка и одно имя файла. Обратите внимание, что-d
это расширение GNU; Если у вас есть только стандарт,read
эта техника не будет работать, и у вас мало возможностей.Мы знаем, что
record
переменная состоит из трех частей, все разделены символами точки. С помощьюcut
утилиты можно извлечь часть из них.Здесь вся запись передается туда
printf
и обратноcut
; в Баш вы могли бы упростить это далее , используя здесь строку дляcut -d. -3f- <<<"$record"
для лучшей производительности. Мы расскажемcut
две вещи: во-первых-d
, для этого необходим определенный разделитель для идентификации полей (как сsort
разделителем.
). Второеcut
указывает-f
на печать только значений из определенных полей; список полей представлен в виде диапазона,3-
который указывает значение из третьего поля и из всех следующих полей. Это означает, чтоcut
будет считывать и игнорировать все, вплоть до секунды.
, найденной в записи, а затем напечатает остаток, который является частью пути к файлу.Распечатав новый путь к файлу, нет необходимости продолжать: выходить
break
из цикла, не давая ему перейти ко второму пути к файлу.Осталось только запустить
tail
путь к файлу, возвращаемый этим конвейером. Вы, возможно, заметили в моем примере, что я сделал это, заключив конвейер в подоболочку; то, что вы, возможно, не заметили, это то, что я заключил подоболочку в двойные кавычки. Это важно, потому что, наконец, даже при всех этих усилиях по обеспечению безопасности для любых имен файлов расширение без кавычек может все же сломать. Более подробное объяснение доступно , если вы заинтересованы. Вторым важным, но легко упускаемым из виду аспектом вызоваtail
является то, что я предоставил ему опцию--
перед расширением имени файла. Это будет инструктироватьtail
что больше никаких опций не указывается, и все, что следует за ним, является именем файла, что позволяет безопасно обрабатывать имена файлов, начинающиеся с-
.источник
tail -f $(find . -type f -exec stat -f "%m {}" {} \;| sort -n | tail -n 1 | cut -d ' ' -f 2)
head
иtail
не принимают переключатели, чтобы заставить их работать на вводе с нулевым разделением». Моя заменаhead
:… | grep -zm <number> ""
.Если вы беспокоитесь о именах файлов с пробелами,
источник
Ты можешь использовать:
$()
Конструкция начинает подоболочку , которая запускает командуls -1t
(листинг всех файлов в порядке времени, по одному в строке) и трубопроводов , что через ,head -1
чтобы получить первую строку (файл).Выходные данные этой команды (самый последний файл) затем передаются для
tail
обработки.Имейте в виду, что это рискует получить каталог, если это самая последняя созданная запись каталога. Я использовал этот трюк в псевдониме для редактирования самого последнего файла журнала (из вращающегося набора) в каталоге, который содержал только эти файлы журнала.
источник
-1
не обязательно,ls
делает это для вас, когда оно в трубе. Сравнитеls
иls|cat
, к примеру.В системах POSIX нет способа получить «последнюю созданную» запись каталога. Каждая запись в каталоге имеет
atime
,mtime
иctime
, в отличие от Microsoft Windows,ctime
означает не CreationTime, а «Время последнего изменения статуса».Таким образом, лучшее, что вы можете получить, это «привязать последний недавно измененный файл», что объясняется в других ответах. Я бы пошел для этой команды:
Обратите внимание на кавычки вокруг
ls
команды. Это заставляет фрагмент работать практически со всеми именами файлов.источник
Если вы просто хотите увидеть изменение размера файла, вы можете использовать часы.
источник
В
zsh
:Смотрите: http://zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Qualifiers , здесь
m
обозначает время модификацииm[Mwhms][-|+]n
, а предшествующееo
означает, что оно отсортировано одним способом (O
сортирует другим способом). Имеются в.
виду только обычные файлы. В скобках[1]
выбирается первый элемент. Чтобы выбрать три использования[1,3]
, чтобы получить самое старое использование[-1]
.Это приятно коротко и не использует
ls
.источник
Вероятно, есть миллион способов сделать это, но я бы сделал так:
Биты между обратными чертами (кавычки, подобные символам) интерпретируются, и результат возвращается в tail.
источник
Простой:
у меня просто отлично работает
Проблема в том, чтобы получить файлы, сгенерированные после запуска команды tail. Но если вам это не нужно (поскольку все вышеперечисленные решения не заботятся об этом), звездочка - это просто более простое решение, IMO.
источник
источник
Кто-то опубликовал его, а затем по какой-то причине стер его, но это единственный, который работает, так что ...
источник
ls
не самая разумная вещь ...Объяснение:
источник
источник