Я новичок в написании сценариев оболочки, поэтому мне нужна помощь, чтобы решить эту проблему.
У меня есть каталог, который содержит файлы в следующем формате. Файлы находятся в директории с именем / 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
Что мне нужно сделать, это выяснить, какой из этих файлов имеет самую новую дату, используя метку времени в имени файла, а не системную метку времени, и сохранить имя файла в переменной, переместить его в другой каталог и переместить остальные в другой каталог.
Для тех, кто просто хочет получить ответ , вот он:
ls | sort -n -t _ -k 2 | tail -1
Вот мыслительный процесс, который привел меня сюда.
Я предполагаю, что часть [ДИАПАЗОН] может быть чем угодно.
Начните с того, что мы знаем.
Нам нужно найти самый последний файл [ГГГГММДД] в каталоге, и нам нужно чтобы сохранить это имя файла.
Доступные инструменты (я перечисляю только соответствующие инструменты для этой проблемы ... их выявление станет проще с практикой):
Думаю, 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/ /_/'
Здесь есть полезная информация, но я уверен, что большинство людей не собираются читать так до конца.
Это должно работать:
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
, чтобы повлиять на это.
Используйте:
ls -r -1 AA_*.dat | head -n 1
(при условии, что нет других файлов, соответствующих AA _ *. Dat
)
Из-за соглашения об именах файлов, алфавитный порядок совпадает с порядком дат. Я почти уверен, что в bash '*' расширяется в алфавитном порядке (но не может найти никаких доказательств на странице руководства), ls определенно делает, поэтому файл с самой последней датой , будет последним по алфавиту.
Следовательно, в bash
mv $(ls | tail -1) first-directory
mv * second-directory
должен помочь.
Если вы хотите уточнить выбор файла, замените *
чем-нибудь другим, например AA _ *. Dat