Shell script: получить имя последнего файла в папке в алфавитном порядке

У меня есть папка с резервными копиями из базы данных MySQL, которые создаются автоматически. Их имя состоит из даты создания резервной копии, например:

2010-06-12_19-45-05.mysql.gz  
2010-06-14_19-45-05.mysql.gz  
2010-06-18_19-45-05.mysql.gz  
2010-07-01_19-45-05.mysql.gz

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

В оболочке script я хотел бы сделать что-то вроде

LAST_BACKUP_FILE= ???
gunzip $LAST_BACKUP_FILE;

Ответы

Ответ 1

ls -1 | tail -n 1

Если вы хотите назначить эту переменную, используйте $(...) или обратные ссылки.

FILE=`ls -1 | tail -n 1`
FILE=$(ls -1 | tail -n 1)

Ответ 2

@Sjoerd ответ правильный, я просто выберу несколько нитей из него:

  • вам не нужен параметр -1 для принудительного использования одного пути на строку, если вы где-то подключаете выход:

    ls | tail -n 1
    
  • вы можете использовать -r, чтобы получить листинг в обратном порядке, и взять первый:

    ls -r | head -n 1
    
  • gunzip some.log.gz будет записывать несжатые данные в some.log и удалять some.log.gz, что может быть или не быть тем, что вы хотите (вероятно, нет). если вы хотите сохранить сжатый источник, переведите его в gunzip:

    gunzip < some.file.gz
    
  • вы можете защитить script от ситуации, когда каталог не содержит файлов, поскольку

    gunzip $empty_variable
    

распространяется только на

    gunzip

и такой вызов будет бесконечно ждать для данных на стандартном вводе:

    latest="$(ls -r /some/where/*.gz | head -1)"
    if test -z "$latest"; then
      # there no logs yet, bail out
      exit
    fi
    gunzip < $latest

Ответ 3

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

for LAST_BACKUP_FILE in *; do : ; done

for LAST_BACKUP_FILE in * циклически перемещается по каждому имени файла по порядку в текущем каталоге, сохраняя каждый в $LAST_BACKUP_FILE

do : ничего не делает

done заканчивается после последнего файла

Теперь последний файл хранится в $LAST_BACKUP_FILE.

Если вам нужен первый файл, используйте это:

for FIRST_BACKUP_FILE in *; do break; done

Оператор break выпрыгивает из цикла после того, как первый файл хранится в $FIRST_BACKUPT_FILE.

Ответ 4

Оболочка более мощная, чем многие думают. Просто пусть это сработает для вас. Предполагая имена файлов без пробелов,

set -- $(ls -r *.gz)
LAST_BACKUP_FILE=$1

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

set -- *.gz
shift $(($# - 1))
LAST_BACKUP_FILE=$1