Получить новейший файл на основе метки времени

Я новичок в написании сценариев оболочки, поэтому мне нужна помощь, чтобы решить эту проблему.

У меня есть каталог, который содержит файлы в следующем формате. Файлы находятся в директории с именем / input / external / data

AA_20100806.dat
AA_20100807.dat
AA_20100808.dat
AA_20100809.dat
AA_20100810.dat
AA_20100811.dat
AA_20100812.dat

. Как видите, имя файла файла содержит временную метку. то есть [ДИАПАЗОН] _ [ГГГГММДД]. dat

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

8
задан ziggy 16 August 2010 в 17:25
поделиться

6 ответов

Для тех, кто просто хочет получить ответ , вот он:

ls | sort -n -t _ -k 2 | tail -1

Вот мыслительный процесс, который привел меня сюда.

Я предполагаю, что часть [ДИАПАЗОН] может быть чем угодно.

Начните с того, что мы знаем.

  • Рабочий каталог: / incoming / external / data
  • Формат файлов: [ДИАПАЗОН] _ [ГГГГММДД] .dat

Нам нужно найти самый последний файл [ГГГГММДД] в каталоге, и нам нужно чтобы сохранить это имя файла.

Доступные инструменты (я перечисляю только соответствующие инструменты для этой проблемы ... их выявление станет проще с практикой):

Думаю, sed нам не нужен, поскольку мы можем работать со всем выводом команды ls. Используя ls, awk, sort и tail, мы можем получить нужный файл следующим образом (имейте в виду, что вам нужно будет проверить синтаксис на соответствие тому, что будет принимать ваша ОС):

NEWESTFILE=`ls | awk -F_ '{print $1 $2}' | sort -n -k 2,2 | tail -1`

Тогда просто нужно поставить подчеркивание обратно, что не должно быть слишком сложно.

РЕДАКТИРОВАТЬ: У меня было немного времени, поэтому я решил исправить команду, по крайней мере, для использования в Solaris.

Вот запутанный первый проход (предполагается, что ВСЕ файлы в каталоге имеют один и тот же формат: [RANGE] _ [yyyymmdd] .dat). Я уверен, что есть способы сделать это лучше, но это работает с моими собственными тестовыми данными (на самом деле, я нашел лучший способ только сейчас; см. Ниже):

ls | awk -F_ '{print $1 " " $2}' | sort -n -k 2 | tail -1 | sed 's/ /_/'

... при написании этого я обнаружил, что вы можете просто сделать это:

ls | sort -n -t _ -k 2 | tail -1

Я разобью это на части.

ls

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

awk -F_ '{print $1 " " $2}'

Это команда AWK. он позволяет вам взять строку ввода и изменить ее определенным образом. Здесь все, что я делаю, это указываю, что awk должен разбивать ввод везде, где есть подчеркивание (_). Я делаю это с помощью опции -F. Это дает мне две половины каждого файла. Затем я приказываю awk вывести первую половину ($ 1), за которой следует пробел ("") , затем вторая половина (2 доллара). Обратите внимание, что пространство было той частью, которой не хватало в моем первоначальном предложении. Кроме того, в этом нет необходимости, поскольку вы можете указать разделитель в приведенной ниже команде сортировки.

Теперь вывод разбивается на [ДИАПАЗОН] [ггггммдд] .dat в каждой строке. Теперь мы можем отсортировать это:

sort -n -k 2

Он берет ввод и сортирует его на основе 2-го поля. Команда sort по умолчанию использует пробелы в качестве разделителя. При написании этого обновления я нашел документацию по сортировке, которая позволяет указать разделитель, поэтому AWK и SED не нужны. Возьмите ls и пропустите его через следующую сортировку:

sort -n -t _ -k 2

Это дает тот же результат. Теперь вам нужен только последний файл, поэтому:

tail -1

Если вы использовали awk для разделения файла (который просто добавляет дополнительную сложность, так что не делайте этого глупо ), вы можете заменить пробел на снова подчеркивание с помощью sed:

sed 's/ /_/'

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

20
ответ дан 5 December 2019 в 05:44
поделиться

Это должно работать:

newest=$(ls | sort -t _ -k 2,2 | tail -n 1)
others=($(ls | sort -t _ -k 2,2 | head -n -1))

mv "$newest" newdir
mv "${others[@]}" otherdir

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

3
ответ дан 5 December 2019 в 05:44
поделиться

Используйте:

ls -r -1 AA_*.dat | head -n 1

(при условии, что нет других файлов, соответствующих AA _ *. Dat )

1
ответ дан 5 December 2019 в 05:44
поделиться

Попробуйте:

$ ls -lr

Надеюсь, это поможет.

2
ответ дан 5 December 2019 в 05:44
поделиться
ls -1 AA* |sort -r|tail -1
1
ответ дан 5 December 2019 в 05:44
поделиться

Из-за соглашения об именах файлов, алфавитный порядок совпадает с порядком дат. Я почти уверен, что в bash '*' расширяется в алфавитном порядке (но не может найти никаких доказательств на странице руководства), ls определенно делает, поэтому файл с самой последней датой , будет последним по алфавиту.

Следовательно, в bash

mv $(ls | tail -1) first-directory
mv * second-directory

должен помочь.

Если вы хотите уточнить выбор файла, замените * чем-нибудь другим, например AA _ *. Dat

1
ответ дан 5 December 2019 в 05:44
поделиться