Ситуация: В Linux у меня есть родительская папка почти с 100 папками различных имен. Каждая папка имеет файл ResourceParent.xml
и сотни различных номеров версий, каждые из которых имеют свое собственное ResourceVer.xml
файл. Я интересуюсь обоими ResourceParent.xml
в 1-й папке уровня и ResourceVer.xml в папке Последней версии (самое большое количество), например. ver548
.
Я должен искать в каждом файле 3 тега .txt|.csv|.xls
и возвратите информацию в этих тегах в файл report.txt. Теги обычно на той же строке, таким образом, я думаю Grep, в порядке.
Что я попробовал:
grep -nr -E ".txt|.csv|.xls" . > /dir/to/the/ReportFile.txt
Это берет слишком долго, поскольку это ищет в каждых из тысяч каталогов и производит много ненужных дублированных данных.
Кроме того, я попытался войти в каждую папку в зависимости от того, что я ищу и запускаю этот скрипт, который является уменьшенными дубликатами немного лучшего ре и более соответствующими данными, но это является все еще слишком громоздким.
Вопрос: Как делают я запускаю скрипт Linux для поиска тегов в файловой структуре, которая похожа на это: Теги интереса внутри .xml файлы:
".txt|.csv|.xls"
текущее местоположение:
/dir
Файл интереса 1:
/dir/par/ResourceParent.xml
Файл интереса 2:
(нужно последнее ver число),
/dir/par/ver###/ResourceVer.xml
Необходимый выходной файл:
ResourceReport.txt
Обновление
Я нашел ls | tail -1
выбирает папку с самым большим ver числом. Таким образом, я думаю, что ответ включает это..
Возможно, с двумя командами...
grep --include="ResourceParent.xml" -r -E '.txt|.csv|.xls' > file
for d in par*; a=("$d"/*); b=($(sort -V <<<"${a[*]}")); grep -HE '.txt|.csv|.xls' "${b[@]: -1}"/*; done >> file
Второй помещает содержание каждого каталога в par
уровень в массив, отсортированный по номеру версии так, чтобы можно было искать просто последний объект в массиве. Это, кажется, работает (я получаю последний номер версии), и только занимает несколько секунд на моей тестовой структуре каталогов (первая команда сопровождает вдвое более длинный).
Если Ваши номера версий дополнены так, чтобы они отсортировали естественно для второй команды, Вы смогли бы использовать просто:
for d in par*; a=("$d"/*); grep -HE '.txt|.csv|.xls' "${a[@]: -1}"/*; done >> file
Я имею в виду, ли Ваши числа ver1
ver2
... ver100
, необходимо будет отсортировать массив, но если они ver001
, ver002
... ver100
, Вы не должны будете сортировать массив, потому что это будет в правильном порядке так или иначе.
Вы, возможно, должны заменить "${b[@]: -1}"/*
с "${b[@]: -1}"/ResourceVer.xml
. Я не создал другие файлы. Необходимо будет, по-видимому, также заменить par*
с чем-то (я думаю, что Вы сказали, у Вас есть приблизительно 100 каталогов на этом уровне).
Но возможно Вы хотели данные, отсортированные по каталогам на уровне par
так, чтобы Вы добрались
data from par1/ResourceParent.xml
data from par1/ver{latest}/ResourceVer.xml
data from par2/ResourceParent/xml
data from par2/ver{latest}/ResourceVer.xml
Вы могли выполнить некоторую обработку текста на выходном файле, но это зависит как Ваш par
каталоги называют. Так как я назвал их par1
par2
... par200
sort -V file >> betterfile
желание сделать то задание, принимая имена файлов не имело никаких новых строк.
Вы могли также урезать имена файлов при помощи grep -h
(вместо -H
) в исходных командах (хотя это означало бы, что Вы не могли отсортировать данные впоследствии по вышеупомянутому методу), или по обработке текста в конце, например, если бы Ваши имена файлов не имеют никаких двоеточий или новых строк, это было бы довольно надежно:
sed 's/^[^:]*://' file
Можно записать в файл вместо stdout путем добавления -i
флаг к sed
после тестирования.
Благодаря John1024, ответ которого на U&L обеспечивает отличный способ получить последнее имя файла, которое не полагается на парсинг вывода ls
или find
или бесплатно цикл по структуре для подсчета повторений.