Помогите с Bash-скриптом или какой-нибудь программой для сортировки файлов и перемещения в разные папки

Есть ли кто-нибудь, кто может помочь мне отсортировать некоторые файлы с помощью bash-скрипта или терминальных команд (или даже небольшой Java-программы), которые можно использовать для сортировки и перемещения файлов в новые папки? Я пытался в течение нескольких дней, но не понял это.

У меня есть папка с названием «веб-страницы» с сотнями HTML-файлов. Грубо говоря, они разделены на три категории, поэтому мне нужно будет запустить один сценарий три раза с разными переменными или сценарий, который может выполнять всю сортировку и перемещение одновременно.

Я хочу найти определенные строки в файлах, а затем отправить соответствующие файлы в новые папки. Чтобы упростить, некоторые из веб-страниц посвящены политике, некоторые о бизнесе, а некоторые о компьютерах. Итак, допустим, я хочу найти во всех файлах в папке «webpages» слова «выборы», «фондовый рынок» и «с открытым исходным кодом» и переместить файлы, содержащие слово «выборы», в папку под названием «политика» файлы, содержащие слово «фондовый рынок», в папку, называемую «бизнес», и файлы, содержащие термин «открытый исходный код», в папку, называемую «компьютеры».

Как я уже сказал, я пытался понять это, но меня просто посмеяли за мои усилия. Я не эксперт. Спасибо!

0
задан 30 March 2015 в 23:05

3 ответа

Предположим, что у Вас есть следующие файлы в текущем каталоге:

  • 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

Удостоверяются, что у Вас есть резервное копирование прежде, чем выполнить это, на всякий случай оно не перемещает их, как Вы хотите.

2
ответ дан 30 March 2015 в 23:05

Я думаю, что некоторое простое волшебство удара могло бы добиться цели:

#!/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
2
ответ дан 30 March 2015 в 23:05

Вот несколько способов сделать то, что Вы хотите:

1. 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 только выполняется, если первое было успешно, если файл соответствовал шаблону.

2. 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) было успешно.

3. Bash.

Этот сценарий очень похож на тот в очень хорошем ответе @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" 
2
ответ дан 30 March 2015 в 23:05

Другие вопросы по тегам:

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