如何重构查找| xargs one liner to a human readable code

时间:2015-10-02 19:54:04

标签: bash find xargs

我已经写了一个OCR包装批和& tesseract和abbyyocr11的服务脚本在此处找到:https://github.com/deajan/pmOCR

main函数是一个find命令,它使用-print0将它的参数传递给xargs,以便处理特殊的filenmames。 find命令变得越来越复杂,最终成为一个很难维护的非常长的衬管:

find "$DIRECTORY_TO_PROCESS" -type f -iregex ".*\.$FILES_TO_PROCES" ! -name "$find_excludes" -print0 | xargs -0 -I {} bash -c 'export file="{}"; function proceed { eval "\"'"$OCR_ENGINE_EXEC"'\" '"$OCR_ENGINE_INPUT_ARG"' \"$file\" '"$OCR_ENGINE_ARGS"' '"$OCR_ENGINE_OUTPUT_ARG"' \"${file%.*}'"$FILENAME_ADDITION""$FILENAME_SUFFIX$FILE_EXTENSION"'\" && if [ '"$_BATCH_RUN"' -eq 1 ] && [ '"$_SILENT"' -ne 1 ];then echo \"Processed $file\"; fi && echo -e \"$(date) - Processed $file\" >> '"$LOG_FILE"' && if [ '"$DELETE_ORIGINAL"' == \"yes\" ]; then rm -f \"$file\"; fi"; }; if [ "'$CHECK_PDF'" == "yes" ]; then if ! pdffonts "$file" 2>&1 | grep "yes" > /dev/null; then proceed; else echo "$(date) - Skipping file $file already containing text." >> '"$LOG_FILE"'; fi; else proceed; fi'

有没有更好的方法将查找结果传递给人类可读的功能(不会影响太快的速度)?

感谢。

4 个答案:

答案 0 :(得分:3)

请勿使用bash -c。您已经承诺从bash命令为每个文件启动一个新的find进程,因此只需将代码保存到文件中并使用

运行该文件
find "$DIRECTORY_TO_PROCESS" -type f -iregex ".*\.$FILES_TO_PROCES" \
     ! -name "$find_excludes" -print0 |
     xargs -0 -I {} bash script.bash {}

答案 1 :(得分:2)

好的,创建脚本,然后运行find。

#!/bin/bash

trap cleanup EXIT
cleanup() { rm "$script"; }

script=$(mktemp)
cat <<'END' > "$script"
########################################################################
file="$1"

function proceed { 
    "$OCR_ENGINE_EXEC" "$OCR_ENGINE_INPUT_ARG" "$file" "$OCR_ENGINE_ARGS" "$OCR_ENGINE_OUTPUT_ARG" "${file%.*}$FILENAME_ADDITION$FILENAME_SUFFIX$FILE_EXTENSION"
    if [ "$_BATCH_RUN" -eq 1 ] && [ "$_SILENT" -ne 1 ]; then 
        echo "Processed $file"
    fi
    echo -e "$(date) - Processed $file" >> "$LOG_FILE"
    if [ "$DELETE_ORIGINAL" == "yes" ]; then 
        rm -f "$file"
    fi
}

if [ "$CHECK_PDF" == "yes" ]; then 
    if ! pdffonts "$file" 2>&1 | grep "yes" > /dev/null; then 
        proceed
    else 
        echo "$(date) - Skipping file $file already containing text." >> '"$LOG_FILE"'; 
    fi
else 
    proceed
fi
########################################################################
END

find "$DIRECTORY_TO_PROCESS" -type f \
                             -iregex ".*\.$FILES_TO_PROCES" \
                           ! -name "$find_excludes" \
                             -exec bash "$script" '{}' \;

引用了heredoc的'END',因此在脚本实际执行之前不会扩展变量。

答案 2 :(得分:2)

您可以完全替换find。它在bash 4(我将在此处显示)中更容易,但在bash 3中可行。

proceed () {
  ...
}

shopt -s globstar

extensions=(pdf tif tiff jpg jpeg bmp pcx dcx)
for ext in "${extensions[@]}"; do
  for file in /some/path/**/*."$ext"; do
    [[ ! -f $file || $file = *_ocr.pdf ]] && continue
    # Rest of script here
  done
done

bash 4之前,您可以编写自己的递归函数以通过目录层次结构进行下载。

descend () {
    for fd in "$1"/*; do
        if [[ -d $fd ]]; then
            descend "$fd"
        elif [[ ! -f $fd || $fd != *."$ext" || $fd = *_ocr.pdf ]]; then
            continue
        else
            # Rest of script here
        fi
     done
 }

 for ext in "${extensions[@]}"; do
     descend /some/path "$ext"
 done

答案 3 :(得分:0)

我用带替换查找命令的while循环完成了操作,即:

while(true){
     var request = (HttpWebRequest)WebRequest.Create(URL);
     var request2 = (HttpWebRequest)WebRequest.Create(URL);
     try {
          using (var response = (HttpWebResponse)request.GetResponse()) { 
               Console.WriteLine(response.Headers);
          }
          using (var response2 = (HttpWebResponse)request2.GetResponse()) {
               Console.WriteLine(response2.Headers);
          }
     }
     catch (WebException e) {
          Console.WriteLine(e);
     }
     Thread.Sleep(2000); //wait for sending next request
}

while循环从文件变量中的find命令读取每个文件。 在while中使用-d $'\ 0',在find命令中使用-print0有助于处理特殊的文件名。