Есть ли кто-нибудь, кто может помочь мне отсортировать некоторые файлы с помощью bash-скрипта или терминальных команд (или даже небольшой Java-программы), которые можно использовать для сортировки и перемещения файлов в новые папки? Я пытался в течение нескольких дней, но не понял это.
У меня есть папка с названием «веб-страницы» с сотнями HTML-файлов. Грубо говоря, они разделены на три категории, поэтому мне нужно будет запустить один сценарий три раза с разными переменными или сценарий, который может выполнять всю сортировку и перемещение одновременно.
Я хочу найти определенные строки в файлах, а затем отправить соответствующие файлы в новые папки. Чтобы упростить, некоторые из веб-страниц посвящены политике, некоторые о бизнесе, а некоторые о компьютерах. Итак, допустим, я хочу найти во всех файлах в папке «webpages» слова «выборы», «фондовый рынок» и «с открытым исходным кодом» и переместить файлы, содержащие слово «выборы», в папку под названием «политика» файлы, содержащие слово «фондовый рынок», в папку, называемую «бизнес», и файлы, содержащие термин «открытый исходный код», в папку, называемую «компьютеры».
Как я уже сказал, я пытался понять это, но меня просто посмеяли за мои усилия. Я не эксперт. Спасибо!
Предположим, что у Вас есть следующие файлы в текущем каталоге:
a/sm1
, с содержанием "фондовый рынок b" b/sm2
, с содержанием "x фондовый рынок y" sm3
, который делает не , содержит "фондовый рынок" destination
, каталог, где Вы хотите переместить файлы, содержащие "фондовый рынок" . Позволяют нам найти все файлы (типа f
= файл) в текущем каталоге (.
):
$ find . -type f
./a/sm1
./sm3
./b/sm2
, Но sm3
не содержит "фондовый рынок", мы не хотим его. В этом списке файлов, которые мы имеем теперь, давайте искать "фондовый рынок" и только отобразим файлы, которые соответствуют:
$ find . -type f | xargs grep --files-with-matches "stock market"
./a/sm1
./b/sm2
Теперь позволяют нам получить каждый из файлов, которые мы получили, и переместите их в destination
каталог:
$ for f in $(find . -type f | xargs grep --files-with-matches "stock market"); do mv $f destination/; done
Удостоверяются, что у Вас есть резервное копирование прежде, чем выполнить это, на всякий случай оно не перемещает их, как Вы хотите.
Я думаю, что некоторое простое волшебство удара могло бы добиться цели:
#!/bin/bash
dir1=""
dir2=""
dir3=""
shopt -s nullglob
for i in *.html)
do if [ "$(grep 'keyword1' $i)" != "" ]; then
mv -vf "$i" "$dir1"
elif [ "$(grep 'keyword2' $i)" != "" ]; then
mv -vf "$i" "$dir2"
elif [ "$(grep 'keyword3' $i)" != "" ]; then
mv -vf "$i" "$dir3"
else
echo "$i">>nomatch
fi
done
cat nomatch
Вот несколько способов сделать то, что Вы хотите:
find
find . -iname '*html' -type f -exec grep -q election "{}" \; -and -exec mv {} politics/ \;
Здесь, мы используем находку -exec
опция:
-exec command ;
Execute command; true if 0 status is returned. All following
arguments to find are taken to be arguments to the command until
an argument consisting of `;' is encountered. The string `{}'
is replaced by the current file name being processed
Так, первое -exec
ищет файл (здесь, представленный {}
) для election
и второй формует перемещение. -and
гарантирует что второе -exec
только выполняется, если первое было успешно, если файл соответствовал шаблону.
find
И оболочка.Это - тот же основной подход как тот в ответе Cos64, но с несколькими улучшениями.
find . -iname '*html' -type f -print0 |
while IFS= read -r -d '' file; do
grep -q election "$file" && mv "$file" politics/
done
find
команда найдет все файлы (-type f
) чье имя заканчивается в .html
(или .HTML
, -iname
нечувствительно к регистру), и распечатайте их разделенный Нулевым символом. Это необходимо, потому что имена файлов в *отклоняют системы, может содержать любой символ кроме /
и \0
(ПУСТОЙ УКАЗАТЕЛЬ). Так, у Вас могут быть файлы с пробелами, новыми строками и любым другим странным символом. Их нужно рассматривать особенно. while IFS= read -r -d '' file; do ... done
: это выполняет итерации по выводу find
, сохранить каждый файл как $file
. IFS=
ни на что устанавливает разделитель поля ввода, что означает, что мы можем иметь дело с пробелами в именах файлов правильно. -d ''
заставляет его читать \0
- разделенные строки и -r
позволяет ему иметь дело с именами файлов, содержащими \
. grep -q election "$file"
: ищите файл шаблон. -q
подавляет нормальный вывод и делает grep
тихий. && echo mv "$file" politics/
: &&
гарантирует, что эта команда только выполняется если предыдущая ( grep
) было успешно. Этот сценарий очень похож на тот в очень хорошем ответе @WilhelmErasmus с различием, что i) это может взять набор шаблонов и замен из командной строки и ii) это также находит файлы в подкаталогах.
#!/usr/bin/env bash
## Exit if no arguments were given
[ -z "$1" ] && echo "At least two arguments are needed." >&2 && exit 1
## Collect the arguments
args=("$@")
## Declare the $dirs associative array
declare -A dirs
## Save the arguments given in the $dirs array.
## $# is the number of arguments given, so this
## will iterate over of them, reading two by two.
for ((i=0;i<$#;i+=2));
do
## The arguments are pairs of patterns and target directories.
## Set the value of this pattern to the value of the next argument,
## its target directory.
dirs[${args[$i]}]="${args[i+1]}"
done
## Ignore globs that match no files
shopt -s nullglob
## This enables ** to match subdirectories
shopt -s globstar
## Find all .html files
for file in **/*{html,htm,HTM,HTML}
do
matched=0;
for pat in "${!dirs[@]}"
do
## Does this file match the pattern?
## The `-q` suppresses grep's output.
grep -q "$pat" "$file" &&
## Set matched to 1 if the file matches.
matched=1 &&
## If the grep succeeded, move the file
## to the corresponding directory
mv "$file" "${dirs[$pat]}" &&
## If the move succeeded, break the loop
## and move to the next pattern.
break
done
## Report files that didn't match
[[ "$matched" -eq 0 ]] && printf "No matches for '%s'\n" "$file" >&2
done
Запустите скрипт, дающий его названия шаблонов и их целей. Например, с теми в Вашем вопросе:
bash move_files.sh "election" "politics" "stock market" "business" "open source" "computers"