単純なシェルスクリプトが何千ものファイルを繰り返すことができません。通常は起動しますが、しばらくすると「一致する `」を探している間に予期しないEOFが発生します。

単純なシェルスクリプトが何千ものファイルを繰り返すことができません。通常は起動しますが、しばらくすると「一致する `」を探している間に予期しないEOFが発生します。

問題のあるシェルスクリプト

あなたがよりよく理解できるように私がやろうとしていることを説明します。私のディレクトリに100個の.torrentファイルがあるとしましょう。 BitTorrent クライアントに追加すると、そのうちの 2 つがそれぞれ xxx.epub と yyy.epub をダウンロードしますが、100 個のうちの 2 つかどうかはわかりません。

したがって、私のスクリプトが行うことは、(1)findすべての.torrentファイルを繰り返し、pwd各.torrentファイルを渡すことです。その後、transmission-show.torrentファイルを解析し、人間が読める形式でメタデータを出力します。次にそれを使用して、急流はawkダウンロードするファイル名を取得し、それをリスト.txtに対して実行します。これには、私たちが探しているファイル名(xxx.epubとyyy.epub)が含まれています。

文書: findtor-array.sh

#! /bin/bash
#
# Search .torrent file based on 'Name' field.
#
# USAGE:
# cd ~/myspace # location of .torrent files
# Run `findtor ~/list.txt` (if `findtor.sh` is placed in `~/bin` or `~/.local/bin`)

# Turn the list of file names from ~/list.txt (or any file passed as argument) into an array
readarray -t FILE_NAMES_TO_SEARCH < "$1"

# For each file name from the list...
for FILE_NAME in "${FILE_NAMES_TO_SEARCH[@]}"
do
    # In `pwd` and 1 directory-level under, look for .torrent files and search them for the file name
    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

    # The `transmission-show` command included in `find`, on it own, for clarity:
    # transmission-show xxx.torrent | awk '/^Name: / || /^File: /' | awk -F ': ' '$2 ~ "SEARCH STRING" {getline; print}'
done

私はそのプロセスが単純で正しく行われていると思います(確認していないことを除いて)。しかし、タスク全体がスクリプトに比べて多すぎるようです。スクリプトを実行してから一定時間が経過すると、I Ctrl+ Citまでこれらのエラーが発生し続けるためです。

_: -c: line 0: unexpected EOF while looking for matching `"'
_: -c: line 1: syntax error: unexpected end of file

これらの「スケーリング」の問題はありますか?私が見逃している部分は何であり、それを解決するにはどうすればよいですか?

ベストアンサー1

FILE_NAMEコマンドオプションに直接渡されますbash -c。引用符/シェルコードを含めると、問題が発生する可能性があります。実際、-execfindFILE_NAME任意のコード実行可能。例: この特別なケースでは、入力ファイルに次の行を含めることができます。'; echo "run commands";'

代わりにbash -cループvarを位置引数として渡してください。たとえば、

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

おすすめ記事