Получить новейший файл на основе отметки времени - PullRequest
7 голосов
/ 16 августа 2010

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

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

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

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

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

Ответы [ 7 ]

19 голосов
/ 16 августа 2010

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

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

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

Я предполагаю, что часть [RANGE] может быть чем угодно.

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

  • Рабочий каталог: / входящий / внешний / данные
  • Формат файлов: [RANGE] _ [ГГГГММДД] .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 доллара). Обратите внимание, что место было той частью, которая отсутствовала в моем первоначальном предложении. Кроме того, в этом нет необходимости, поскольку вы можете указать разделитель в команде сортировки ниже.

Теперь вывод делится на [RANGE] [yyyymmdd] .dat в каждой строке. Теперь мы можем отсортировать это:

sort -n -k 2

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

sort -n -t _ -k 2

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

tail -1

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

sed 's/ /_/'

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

3 голосов
/ 16 августа 2010

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

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, чтобы повлиять на это.

2 голосов
/ 16 августа 2010

Попробуйте:

$ ls -lr

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

1 голос
/ 27 марта 2012

Мое решение для этого похоже на другие, но немного проще.

ls -tr | tail -1

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

Это решение не будет работать, если требуемое имя файла имеет начальную точку (например, .profile).

Это решение работает, если имя файла содержит пробел.

1 голос
/ 17 августа 2010

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

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

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

Должен сделать трюк.

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

.
1 голос
/ 16 августа 2010
ls -1 AA* |sort -r|tail -1
1 голос
/ 16 августа 2010

Использование:

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...