Простой сценарий оболочки, неспособный просмотреть тысячи файлов; запускается нормально, но выдает "неожиданный EOF при поиске соответствия `"`" через некоторое время

# get number of lines in the file
n=$( wc -l <file )

# extend the file
awk -v n="$n" 'NR <= n { print $1+1 >>FILENAME }' file

Запустите эти две команды столько раз, сколько пожелаете.

Программа awkпросто добавляет строки к тому же файлу, из которого она читает. Добавляемые данные будут представлять собой существующие числа, увеличенные на единицу.

Если мы не ограничим это числом строк в файле (с NR <= n), оно будет расти бесконечно, пока не заполнит раздел.

1
04.04.2020, 09:43
3 ответа

Основываясь на предложениях @Kusalananda, ответах (@guest и @Jetchisel )и этом подробном ответе Кевина , я придумал это:

#! /bin/bash
#
# Search for 'Name' field match in torrent metadata for all.torrent files in
# current directory and directories 1-level below.
#
# USAGE e.g.:
# cd ~/torrent-files # location of.torrent files
# Run `~/findtor.sh ~/list.txt`

# Get one file name at a time ($FILE_NAME_TO_SEARCH) to search for from list.txt
# provided as argument to this script.
while IFS= read -r FILE_NAME_TO_SEARCH; do

    # `find`.torrent files in current directory and directories 1-level under
    # it. `-print0` to print the full file name on the standard output, followed
    # by a null character (instead of the newline character that `-print` uses).
    #
    # While that's happening, we'll again use read, this time to pass one
    #.torrent file at a time (from output of `find`) to `transmission-show`
    # for the latter to output the metadata of the torrent file, followed by
    # `awk` commands to look for the file name match ($FILE_NAME_TO_SEARCH) from
    # list.txt.
    find. -maxdepth 2 -name '*.torrent' -type f -print0 |
        while IFS= read -r -d '' TORRENT_NAME; do
            transmission-show "$TORRENT_NAME" | awk '/^Name: / || /^File: /' | awk -F ': ' -v search_string="$FILE_NAME_TO_SEARCH" '$2 ~ search_string {getline; print}';
        done >> ~/torrents-found.txt

done < "$1"

Я только что запустил это, и пока все работает отлично. Так что большое спасибо всем причастным!

Хотя я сделал все возможное, любые исправления и дальнейшие предложения приветствуются.

2
28.04.2021, 23:18

Я бы написал так.

#!/usr/bin/env bash

pattern_file="$1"

while IFS= read -r -d '' file; do
    transmission-show "$file" | awk.... "$pattern_file"   ##: Figure out how to do the awk with a file rather than looping through an array.
done < <(find. -maxdepth 2 -name '*.torrent' -type f -print0)

Это следует избегать цитирования ада:-)

Хорошо, может nullglobне нужен.

РЕДАКТИРОВАТЬ:

Попробуйте выполнить команду find и используйте ее в исходном скрипте.

find. -maxdepth 2 -name '*.torrent' -type f -exec bash -c 'transmission-show "$1" | awk "/^Name\: / || /^File\: /" | awk -F ": " "\$2 ~ \"$FILE_NAME\" {getline; print}"' _ {} + >> ~/torrents.txt
0
28.04.2021, 23:18

FILE_NAMEпередается непосредственно в bash -cв опции -execвашей команды find. Это вызывает проблемы, если FILE_NAMEсодержит кавычки/код оболочки. На самом делеможет быть выполнен произвольный код. Пример :В данном конкретном случае входной файл может содержать строку'; echo "run commands";'

Вместо этого передайте переменную цикла в bash -cв качестве позиционного параметра. например.:

find. -maxdepth 2 -name '*.torrent' -type f -exec sh -c '
transmission-show "$2" |
awk -v search="$1" '\''/^Name: / {name = substr($0,7)} /^File: / && name ~ search {print; exit}'\' \
_ "$FILE_NAME" {} \;

Кроме того, кажется неэффективным перебирать все условия поиска для каждого файла. Рассмотрите возможность циклического просмотра файлов и поиска с помощьюgrep -f file:

find. -maxdepth 2 -name '*.torrent' -type f -exec sh -c '
file=$1
shift
if transmission-show "$file" | head -n 1 | cut -d" " -f2- | grep -q "$@"; then
    printf "%s\n" "$file"
fi' _ {} "$@" \;

или безfind:

for file in *.torrent */*.torrent; do
    if transmission-show "$file" | head -n 1 | cut -d' ' -f2- | grep -q "$@"; then
        printf '%s\n' "$file"
    fi
done
  • В приведенном выше примере все аргументы просто передаются в grep, поэтому используется findtor -f ~/list.txtдля получения шаблонов из списка, -Fдля фиксированных строк, -e expressionи т. д.
2
28.04.2021, 23:18

Теги

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