# 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
), оно будет расти бесконечно, пока не заполнит раздел.
Основываясь на предложениях @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"
Я только что запустил это, и пока все работает отлично. Так что большое спасибо всем причастным!
Хотя я сделал все возможное, любые исправления и дальнейшие предложения приветствуются.
Я бы написал так.
#!/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
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
и т. д.