Рекурсивный поиск всех файлов xml в каталоге для определенного тега и поиск значения тега с помощью grep

С оговоркой, что это решение не может обрабатывать такие вещи, как символ перевода строки в имени файла:

mkdir extract_images 2>/dev/null
while IFS= read -r file; do
  mv "$file" extract_images
done < extract_images_list.txt

Он проходит через extract_images_list.txt построчно, считывая их в файл (требуется аргумент -r , чтобы он обрабатывал обратную косую черту как буквальную обратную косую черту, а IFS = не убирает пробелы), затем перемещает каждую строку в каталог extract_images.

2
17.01.2019, 00:17
4 ответа

Вот решение с find , которое также выводит имена файлов, содержащих совпадение:

find . -name "*.xml" -exec grep '<dbname>' {} \;             \
                     -exec echo -e {}"\n" \;                 \
                     | sed 's/<dbname>\(.*\)<\/dbname>/\1/g'

Пояснение

  1. find . -name "* .xml" рекурсивно найти все XML-файлы из текущего каталога
  2. -exec grep '' {} \; в каждом файле искать шаблон
  3. -exec echo -e {} "\ n" \; echo filename + новая строка ( -e опция заставляет интерпретировать эхо \ n )
  4. | sed 's / \ (. * \) <\ / dbname> / \ 1 / g' выводит конвейер на sed для печати только поля, содержащегося между теги.

ПРИМЕЧАНИЕ 1: вы можете отформатировать вывод в своем echo -e ... , чтобы результаты для каждого файла были четко представлены, например добавляя новые строки или строки подчеркивания, в зависимости от того, что вам нужно.

ПРИМЕЧАНИЕ2: путь к каждому файлу будет указан относительно . (например, ./ subfolder1 / file.xml ).Если вам нужен абсолютный путь, введите найдите $ PWD -name ... .

3
27.01.2020, 21:59

Использование правильного синтаксического анализатора XML для синтаксического анализа XML:

shopt -s globstar nullglob
for file in **/*.xml; do 
    dbname=$(xmlstarlet sel -t -v '//dbname' "$file")
    [[ -n "$dbname" ]] && printf "%s\t%s\n" "$file" "$dbname"
done
4
27.01.2020, 21:59

Предположим, у нас есть каталог XMLS , содержащий эти файлы:

cat XMLS/file1
foo bar <dbname>target</dbname> baz
foo foo

cat XMLS/file2
<name>notarget</name>

Я бы использовал эту команду:

grep -r '<dbname>' XMLS/ | sed 's/.*<dbname>\(.*\)<\/dbname>.*/\1/'
target

Как видите, она возвращает значение внутри теги. А не значение внутри тегов .


Флаг -r для grep выполняет рекурсивный поиск.

sed удаляет из строки все, кроме значения target .

0
27.01.2020, 21:59

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

find testmag -type f -name '*.xml' -exec xq -r '..|(.dbname? // empty)' {} +

Это позволит найти все обычные файлы с именами, соответствующими *.xml, в каталоге testmagили ниже него. Для их пакетов будет вызываться xqдля извлечения значения каждого узла dbname, найденного в этих документах.

xq— это анализатор XML, подобный jq-, который распространяется вместе с yqиз https://kislyuk.github.io/yq/

.

Если вам нужны имена всех XML-файлов, содержащих этот узел, вы можете использовать

find testmag -type f -name '*.xml' -exec xq -e '..|(.dbname? // empty)' {} \; -print

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

2
16.05.2021, 08:28

Теги

Похожие вопросы