Справка с помощью скрипта Bash или некоторой программы для сортировки файлов и перемещения в разные папки

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

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

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

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

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

2 ответа

Я думаю, что некоторая простая магия bash может сделать трюк:

#!/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
ответ дан 23 May 2018 в 21:54
  • 1
    1) Любые предложения по лучшей реализации? 3) Зачем нужно увеличивать количество файлов? Он используется как условие else @terdon – Wilhelm Erasmus 30 March 2015 в 21:54
  • 2
    Спасибо, @terdon Для 3), хотя, не будет ли он расти только в том случае, если совпадение не может быть найдено? Это будет цикл через if, elif, elif, а затем запустить раздел else? – Wilhelm Erasmus 30 March 2015 в 23:48
  • 3
    Да, но в следующий раз, когда вы запустите программу, она добавит в файл. Поскольку вы используете >>, файл будет расти при каждом запуске скрипта. – terdon♦ 31 March 2015 в 01:28
  • 4
    И ничего себе, ты сделал домашнее задание! Вы даже добавили nullglob, хорошо сделали и +1 :) – terdon♦ 31 March 2015 в 01:34
  • 5
    Еще одно улучшение, которое вы можете сделать, - сохранить файлы, которые не совпадают в массиве, и напечатать этот массив в конце скрипта. Таким образом, вы избегаете использования временных файлов (вы также избегаете опасности наличия файла с именем nomatch в каталоге, в котором вы его запускаете), и после этого его не нужно очищать. – terdon♦ 31 March 2015 в 01:41

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

1. find

find . -iname '*html' -type f -exec grep -q election "{}" \; -and -exec mv {} politics/ \; 

Объяснение

Здесь мы используем опцию find -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, а второй - заготовку. [F11] гарантирует, что второй -exec будет запущен только в том случае, если первый был успешным, если файл соответствует шаблону.

2. find & amp; shell

Это тот же базовый подход, что и в ответе 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 нечувствительно к регистру) и распечатайте их, разделенные символом NULL. Это необходимо, потому что имена файлов в системах * nix могут содержать любой символ, кроме / и \0 (NULL). Таким образом, вы можете иметь файлы с пробелами, символами новой строки и любым другим странным символом. Их нужно лечить специально. while IFS= read -r -d '' file; do ... done: он выполняет итерацию по выходу find, сохраняя каждый файл как $file. Параметр IFS= устанавливает разделитель полей ввода в нуль, что означает, что мы можем правильно обрабатывать пробелы в именах файлов. [F25] позволяет прочитать \0 -сепаратированные строки, а -r позволяет использовать имена файлов, содержащие \. grep -q election "$file": поиск файла для шаблона. [F30] подавляет нормальный выход и делает 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
ответ дан 23 May 2018 в 21:54
  • 1
    Спасибо!! Я собираюсь настроить некоторые файлы и попробовать свои команды и скрипт, как только смогу. Мне просто нужно исправить установку Ubuntu, которая имеет некоторые проблемы, прежде чем у меня будет время попробовать сценарий. Спасибо вам за помощь! Думаю, на самом деле у меня может быть более тысячи веб-страниц! :) – David 2 April 2015 в 21:12

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

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