Извлеките строки из текстовых файлов и переименуйте их соответственно в bash - PullRequest
1 голос
/ 16 марта 2019

У меня много текстовых файлов, названных случайным образом (что-то вроде 70000 файлов);все, что я знаю, это то, что где-то в первых 30 строках есть две строки формата Author: Samuel Richardson и еще одна строка Title: Clarissa, Volume 5 (of 9).Я не уверен в случае этих двух строк.

Я хочу извлечь заголовок и автора и соответственно переименовать файл, что-то вроде "Clarissa, Volume 5 (of 9) ,___, Samuel Richardson.txt" (я использую ,___,, чтобы были допустимые разделителимежду автором и заголовками.

Мой код:

for filename in *.txt; do

    title=$(head -n 30 $filename.txt | grep -i 'Title:' | sed -n 's/^.*Title: //p')
    author=$(head -n 30 $filename.txt | grep -i 'Author:' | sed -n 's/^.*Author: //p')
    new_name="$title ,___, $author"

    mv $filename $new_name.txt
done

Он не работает должным образом. Подкод

echo "title: $title _"
echo "author: $author _"

new_name="$title ,___, $author"

echo $new_name

выводит на печать следующий вывод

 _tle: Clarissa, Volume 5 (of 9)
 _thor: Samuel Richardson
 ,___, Samuel Richardson)

Более того, я не знаю, как сохранить вычисление извлечения первых 30 строк с помощью команды head в переменную firstlines, чтобы его не пришлось пересчитывать.

Код

firstlines=$(head -n 30 randomname.txt)

и использование title=$($firstlines | grep -i 'Title:' | sed -n 's/^.*Title: //p')

выводит ошибку command not found.

Ответы [ 2 ]

0 голосов
/ 16 марта 2019

@ Комментарий Поши о конце строки является правильным, и ответ @ B.Shefter находится на правильном пути, но имеет ряд проблем (ссылки на переменные без кавычек, основанные на нестандартных свойствах echo и sed), поэтому Я решил переписать (надеюсь) исправленные проблемы.

Также я повторю рекомендацию, которую я дал в комментарии: используйте mv -n или mv -i, чтобы избежать перезаписи файлов, если что-то пойдет не так, и сначала сделайте резервную копию. (В любом случае, у вас есть резервная копия, вы должны всегда иметь резервную копию всего, что вы не хотите потерять.)

В любом случае, вот мое мнение:

#!/bin/bash

for filename in *.txt; do

    # Grab the first 30 lines with carriage returns removed:
    firstlines=$(head -n 30 "$filename" | tr -d '\r')

    # Capture the title and author. Note that sed doesn't have case-insensitive
    # patterns, so use e.g. [Tt] to manually make them case-insensitive. Also, use
    # [[:blank:]]* to allow any number of spaces and/or tabs after the ":".
    title=$(echo "$firstlines" | sed -n 's/^.*[Tt][Ii][Tt][Ll][Ee]:[[:blank:]]*//p')
    if [ -z "$title" ]; then
        echo "Unable to find Title: in $filename; skipping" >&2
        continue
    fi

    author=$(echo "$firstlines" | sed -n 's/^.*[Aa][Uu][Tt][Hh][Oo][Rr]:[[:blank:]]*//p')
    if [ -z "$author" ]; then
        echo "Unable to find Author: in $filename; skipping" >&2
        continue
    fi

    new_name="$title ,___, $author.txt"

    # Note: the filenames here will contain spaces, so double-quoting is *critical*
    mv -i "$filename" "$new_name"
done
0 голосов
/ 16 марта 2019

@ Поши прав: твоя главная проблема - окончания строк. Похоже, что каждое окончание строки включает возврат каретки (\r). Сам по себе \r просто перемещает курсор назад к началу строки. В сочетании с \n он работает нормально - потому что он перемещается в начало следующей строки - но сам по себе он вызывает то, что вы видите: какой-то текст, после которого курсор возвращается к начало строки, затем текст перезаписывает то, что было изначально.

РЕДАКТИРОВАТЬ: Вероятно, это поможет, если я включу решение для этого. Примерно так должно работать, вставлять перед присваиванием new_name:

title=$(echo -e $title | sed 's/\r//')
author=$(echo -e $author | sed 's/\r//')

Что касается вашей второй проблемы, то причина, по которой вы получаете command not found, заключается в том, что первое слово в переменной $firstlines не является командой. Вы хотите что-то вроде:

title=$(echo -e $firstlines | grep -i 'Title:' | sed -n 's/^.*Title: //p')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...