簡單的shell腳本無法遍歷數千個文件;開始正常,但一段時間後在尋找匹配的'
‘時拋出“意外的EOF”
有問題的 Shell 腳本
讓我解釋一下我正在嘗試做的事情,例如,這樣您就可以更好地理解。假設我在一個目錄中有 100 個 .torrent 文件。如果添加到 bittorrent 客戶端,其中 2 個將分別下載 xxx.epub 和 yyy.epub,但我不知道 100 個中有 2 個。
所以我的腳本所做的是,(1)使用
find
遍歷所有 .torrent 文件pwd
並傳遞每個 .torrent 文件,因為它transmission-show
會解析 .torrent 文件並以人類可讀格式輸出元數據。然後,我們將使用awk
獲取 torrent 文件將下載的文件名並針對 list.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
我認為這個過程很簡單,我做得對(除了沒有檢查,我知道)。但不知何故,整個任務對於腳本來說似乎太多了,因為在執行它之後,它開始連續拋出這些錯誤,直到我
Ctrl
+C
它:_: -c: line 0: unexpected EOF while looking for matching `"' _: -c: line 1: syntax error: unexpected end of file
這些是“縮放”問題嗎?我錯過了什麼,我能做些什麼來解決它?
根據@Kusalananda 的建議、答案(@guest 和@Jetchisel)以及Kevin 的詳細回答,我想出了這個:
#! /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"
我剛剛執行了這個,到目前為止它似乎工作得很好。非常感謝所有參與其中的人!
儘管我已盡力而為,但歡迎任何修復和進一步的建議。
FILE_NAME``bash -c
在您的命令-exec
選項中直接傳遞給。find
如果FILE_NAME
包含引號/shell 程式碼,這會導致問題。事實上,可以執行任意程式碼。範例:在這種特殊情況下,輸入文件可能包含一行'; 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
等。