rm *
отлично работает, если ваш каталог не содержит подкаталогов (см. ответ @kos). Однако, если вам нужно рекурсивное решение, которое также удаляет все подкаталоги, то (, как указал @meesern ,)rm -r *
не то, что вам нужно, поскольку действительно удаляет скрытые файлы и подкаталоги.
Вместо этого вы можете использовать find
для отображения и удаления не -скрытых файлов и подкаталогов (, адаптированных из этого ответа):
find YOUR_DIRECTORY -not -path '*/\.*' -delete
Это приведет к удалению всех не-скрытых файлов в YOUR_DIRECTORY
и всех подкаталогах, которые стали пустыми после удаления не-скрытых файлов.
Он не будет удалять содержимое внутри скрытого каталога (, например. YOUR_DIRECTORY/.foo/bar/baz
). В результате вы можете получить некоторые предупреждения, такие как
find: cannot delete 'some/directory/here': Directory not empty
Но вы можете смело игнорировать их.
Рассматривали ли вы цикл по каждой категории? Вот так:
for i in *.xml; do
for category in $(sed -rn '/^<category>/{s/[^>]*> *([^ <]*).*/\1/p}' "$i"); do
sed -rn "/^<category> *$category/,/^<category>/{s/<url> *([^ <]*).*/\1/p}" "$i" > "$category.log"
done
done
awk -v 'RS=<' -v 'cat=none' -F '>' \
'$1 ~ /^category$/ {gsub(/^ *| *$/,"",$2); cat=$2} \
$1 ~ /^url$/ {print $2 >> cat".log"}' \
*.xml
Это позволяет избежать зацикливания входных файлов и добавит к файлу .log
любую категорию.
Использование назначения разделителя записей awk -v 'RS=<'
будет означать, что тег категории/url будет найден где угодно (, а не только в начале строки ). Новая строка может появиться в любом месте данных xml.
Сочетание этого с установкой разделителя полей на '>'
означает, что первое поле каждой записи будет эквивалентно имени тега xml.
Каждый раз, когда awk встречает запись, где первым полем является «категория», переменная cat
устанавливается на имя этой категории.
Когда awk встречает запись, где первым полем является «url», он добавит этот URL в файл cat.log
.
cat
будет определено как none
для начала. Это предотвращает сбой в случае, если <url>
встречается без какого-либо предшествующего <category>
.
Замена gsub(/^ *| *$/,"",$2)
предназначена для удаления начальных/конечных пробелов для имен категорий, которые появляются в вашем примере входного файла .xml
.
Ни один из вышеперечисленных способов не является надежным. Для правильных входных файлов xml лучше использовать реальный парсер xml, например xmlstarlet . Но для этого также потребуются правильно сформированные xml-файлы (, в примере ввода нет соответствующих тегов <category>
, например ).
Я приготовил это решение:
grep -hP "<category.*>|<url.*>" *.xml | cut -d ">" -f 2 | cut -d "<" -f 1 | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | gawk 'BEGIN { category = ""; } { if (!length($0)) { next; } if (length(category)) { printf("\necho -e \"%s\" >> \"%s.log\"", $0, category); category = ""; } else { category = $0; } } END { printf("\n"); }' | bash
Он ищет все файлы.xml в текущем каталоге и добавляет URL-адрес к файлу, названному в соответствии с категорией, найденной в строке, предшествующей URL-адресу (вы можете проверить вывод, удалив | bash в конце ).
Разрешив, например, grep ()искать шаблон в файлах с именами*.xml , нам не нужно перебирать имена файлов. Опция-h для grep подавляет имена файлов в выводе. Шаблон, переданный grep, является Perl -совместимым регулярным выражением(-P)
Строки, возвращаемые командой grep, явно выглядят так, как показано ниже:
<category> MyMusic </category>
<url>https://www.youtube.com/watch?v=waAlgFq9Xq8123</url>
<category> MyMovies </category>
<url>https://www.youtube.com/watch?v=g4U4BQW9OEk456</url>
<category>Music</category>
<url>https://www.youtube.com/watch?v=waAlg</url>
<category> Music </category>
<url>https://www.youtube.com/watch?v=waAlgFq9Xq8</url>
<category> Movies </category>
<url>https://www.youtube.com/watch?v=g4U4BQW9OEk</url>
мы только что отфильтровали строки с данными, которые нам не нужны. Теперь нам нужно извлечь значения внутри узлов, что сводится к извлечению данных между открывающим и закрывающим тегами, т.е. между знаками > и <(нам все равно какой узел это так, поэтому мы используем «общий» подход ).
Этого можно легко добиться с помощью| cut -d ">" -f 2 | cut -d "<" -f 1
что практически означает брать все с правой стороны (-f 2 )знака > затем, с новым результатом, который у нас есть, возьмите все в левой части (-f 1 )знака <
Что оставляет нас ниже
MyMusic
https://www.youtube.com/watch?v=waAlgFq9Xq8123
MyMovies
https://www.youtube.com/watch?v=g4U4BQW9OEk456
Music
https://www.youtube.com/watch?v=waAlg
Music
https://www.youtube.com/watch?v=waAlgFq9Xq8
Movies
https://www.youtube.com/watch?v=g4U4BQW9OEk
Теперь нам нужно обрезать значения, вот небольшой корректирующий шаг.
Обрезка начальных и конечных пробелов с помощью| sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
С помощью-e sed может выполнять сценарии в том порядке, в котором они заданы, без необходимости передавать дополнительную команду sed (или несколько команд sed для других сценариев ).
Первый скрипт, переданный в sed, обрезает начальный пробел (, т. е. любые [:пробел :] символы в начале строки (@ каждой строки )), а второй обрезает конечный пробел. (т.е. любые [:пробелы :] символы перед концом строки (в каждой строке ).
Теперь у нас есть что-то вроде следующего, и мы почти закончили:
MyMusic
https://www.youtube.com/watch?v=waAlgFq9Xq8123
MyMovies
https://www.youtube.com/watch?v=g4U4BQW9OEk456
Music
https://www.youtube.com/watch?v=waAlg
Music
https://www.youtube.com/watch?v=waAlgFq9Xq8
Movies
https://www.youtube.com/watch?v=g4U4BQW9OEk
Точно так же, как мы пишем эхо-команды для добавления данных в файл, нам нужно что-то, что автоматизирует процесс. Я решил продолжить с gawk. gawk считывает данные построчно и записывает категорию в переменную. Когда он читает другую строку, если переменная категории не пуста, то строка содержит URL-адрес. Используя эту технику, мы можем просто вводить такие команды, как echo -e "current url" >> current _category.log
Обратите внимание на императивное использование >> для добавления новых данных в файл. Использование > запишет только последний URL, и мы получим одну строку для каждой категории!
В результате мы только что записали данные, как показано ниже, в стандартный вывод:
echo -e "https://www.youtube.com/watch?v=waAlgFq9Xq8123" >> "MyMusic.log"
echo -e "https://www.youtube.com/watch?v=g4U4BQW9OEk456" >> "MyMovies.log"
echo -e "https://www.youtube.com/watch?v=waAlg" >> "Music.log"
echo -e "https://www.youtube.com/watch?v=waAlgFq9Xq8" >> "Music.log"
echo -e "https://www.youtube.com/watch?v=g4U4BQW9OEk" >> "Movies.log"
Последний элемент конвейера | bash
обеспечивает передачу эхо-команд в bash для выполнения.
Обратите внимание, что gawk может записывать/добавлять данные в файлы. Но я намеренно хотел иметь наименьший возможный gawk-скрипт.
Tested with Below command and Worked fine
команда
for i in `awk '/\<category\>/{print $2}' filename`; do sed -n '/'$i'/{n;p}' filename | awk -F ">" '{gsub(/<.*/,"",$2);print $2}' > $i.log; done
выход
cat Music.log
https://www.youtube.com/watch?v=waAlgFq9Xq8
cat Movies.log
https://www.youtube.com/watch?v=g4U4BQW9OEk