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

94

Можно ли узнать время, когда файл был открыт в последний раз, и отсортировать все файлы в каталоге по тем временам?

ученик
источник

Ответы:

172

Это зависит от того, что именно вы подразумеваете под «открытым», но в целом да. Обычно записываются три метки времени:

  • mtime- обновляется при изменении содержимого файла. В большинстве случаев это время файла по умолчанию.
  • ctime- обновляется при изменении файла или его метаданных (владелец, разрешения)
  • atime - обновляется при чтении файла

Итак, как правило, вы хотите увидеть atimeфайл. Вы можете получить это с statили с ls. Вы можете использовать ls -luдля этого, хотя я предпочитаю использовать ls -l --time=atime(что должно поддерживаться почти во всех современных дистрибутивах Linux), потому что я использую его не часто, и когда я это делаю, я лучше помню его. И чтобы отсортировать по времени, добавьте -tфлаг в ls. Итак, поехали.

Однако есть большая оговорка. Обновление atime каждый раз, когда файл читается, вызывает много обычно ненужных операций ввода-вывода, замедляя все. Таким образом, большинство дистрибутивов Linux по умолчанию используют noatimeопцию монтирования файловой системы, которая в основном убивает время от времени, или же relatime, которая обновляется только раз после того, как предел превышен (обычно один раз в день) или если файл был фактически изменен с момента предыдущего чтения. Вы можете узнать, активны ли эти опции, запустив mountкоманду.

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

И имейте в виду, что с не "создание"; создание не отслеживается файловыми системами Unix / Linux, что кажется странным, но на самом деле имеет смысл, потому что файловая система не может узнать, является ли она оригиналом - возможно, файл был создан сорок лет назад и скопирован здесь. И, на самом деле, многие файловые редакторы работают, делая копии поверх оригинала. Если вам нужна эта информация, лучше использовать систему контроля версий, например git.

mattdm
источник
9
Я бы дал вам больше +1, если бы мог, просто за то, что вы не назвали ctime «Creation Time».
Jsbillings
2
Согласно man- странице mount, relaytime не имеет ничего общего с дневными ограничениями, а только смотрит на atime относительно mtime и ctime. Если atime старше, чем mtime или ctime, atime обновляется. Если atime новее, чем оба, то он остается один. Цель этого - сохранить связь между atime и mtime / ctime, поскольку некоторые приложения используют эту информацию, например, mutt, чтобы узнать, прочитал ли он ваш почтовый ящик с момента его последнего обновления.
jw013
1
@ jw013 Так было с ядра 2.6.30. Это правда, что некоторые старые дистрибутивы могут не иметь такого поведения. (Но для таких дистрибутивов, как Fedora, это было верно даже тогда, когда я написал оригинальную версию этого ответа три года назад.) Ищите обновленную mountстраницу руководства.
Mattdm
1
lsсокращает время по умолчанию до разумной точности. Чтобы увидеть время с полной точностью, можно использовать --full-time.
JLH
19

ls -ltu список всех файлов, показывая и сортируя по времени доступа.

От man ls:

-u     with -lt: sort by, and show, access time with -l: show access
       time and sort by name otherwise: sort by access time
Шон Дж. Гофф
источник
4

Команда findлучше всего подходит для этого. Смотрите -ctime, -mtimeи -atimeварианты

GBH
источник
3

Если ваш список предназначен для использования человеком, используйте lsодин из флагов сортировки даты ( -tuдля времени доступа (чтения), только -tдля времени модификации (записи) или -tcдля времени изменения индекса). См . Ответ mattdm для получения дополнительной информации (в частности, предостережение относительно -aи определение -c).

Если это для потребления программы, анализ вывода lsпроблематичен . Если ваша оболочка zsh, вам все lsравно это не нужно : у zsh есть глобирующие квалификаторы для сортировки совпадений путем увеличения времени доступа ( *(Oa)), изменения inode ( *(Oc)) или модификации ( *(Om)). Строчные oсортирует по возрасту.

act_on_files_by_date *(Om)

В противном случае, если вы знаете, что имена файлов не содержат символов новой строки или непечатаемых символов (в текущей локали), то вы можете сделать что-то вроде

ls -t | while read -r name; do act_on_one_file "$name"; done
ls -t | xargs -I {} act_on_one_file {}

Если вы хотите вызвать команду для нескольких файлов одновременно, вам нужно больше настроек. Обратите внимание, что act_on_files_by_date $(ls -t)это не работает так, поскольку имена файлов, содержащие символы подстановки или пробелы, будут расширены в результате подстановки команды. Следующий код работает до тех пор, пока ни одно имя файла не содержит символ новой строки или непечатаемый символ:

IFS='
'
set -f
act_on_files_by_date $(ls -t)
set +f
unset IFS

Если вы хотите справиться с произвольными именами файлов, вам будет очень трудно без использования более мощных инструментов, чем стандартная оболочка: zsh, perl, python…

жилль
источник