何も繰り返すことなくテスト実行オプションを作成する正しい方法は何ですか?

何も繰り返すことなくテスト実行オプションを作成する正しい方法は何ですか?

リモートサーバーからファイルを検索してローカルコンピュータに戻すスクリプトを作成しています。まず、ツアーを実行してどの文書をインポートする必要があるかを知ることができたらよかったでしょう。

私は現在私が見つけたいくつかのコードのミックスインとgetopts出力リダイレクトを使用しています。ここ

私の研究では、ZSHまたはBash関数から配列を返すことは非現実的です。このため、繰り返さずにこのスクリプトを書く方法を理解することは困難です。

これは私の現在のスクリプトです。

編集する:いくつかのbashismをzshと混ぜたことを許してください。私はzshを使ってこのスクリプトを書き始めましたが、#!/bin/bash後でzshに切り替えました。

#!/usr/local/bin/zsh
RED='\033[0;31m'
NC='\033[0m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'

dry_run=0
yesterday=1

# Establish -n flag means to do a dry run.
while getopts "ny:" flag; do
    case "$flag" in
        n) dry_run=1 ;;
        y) yesterday=${OPTARG} ;;
        *) echo 'error in command line parsing' >&2
           exit 1
    esac
done
shift $(($OPTIND-1))

# This is the folder I'm interested in getting files from
folder=${1:?"You must define a folder of interest"}

# Check to see if dry-run, if not proceed with copying the files over. 
if [ "$dry_run" -eq 1 ]; then
    print -Pn "\n%S%11F%{Initiating Dry-Run%}%s%f"

    # SSH onto server and find the most recently updated folder.
    # Then place that newest folder and folder of interest into the absolute file path.
    # Then SSH again and use find with that file-path
    # Return array of file paths
    # TODO: **THIS IS THE SECTION I NEED TO REFACTOR INTO A FUNCTION**
    bison_remote_files=($(
        {
            {
                bison_latest_run=$(ssh -qn falcon1 'find /projects/bison/git/* -mindepth 0 -maxdepth 0 -type d -printf "%T@\t%f\n"' |
                    sort -t$'\t' -r -nk1,5 |
                    sed -n "$yesterday"p |
                    cut -f2-)

                bison_remote_path=$(
                    echo $bison_latest_run |
                        awk -v folder="$folder" '{print "/projects/bison/git/"$1"/assessment/LWR/validation/"folder}')

                ssh -qn falcon1 \
                    "find $bison_remote_path -type f -name '*_out.csv' -not -path '*/doc/*' 2>/dev/null" >&3 3>&-; echo "$?"

                print -Pn "\n\n%U%B%13F%{Fetching data from:%}%u %B%12F%{ /projects/bison/git/${bison_latest_run}%}%b%f\n" >&2

            } | {
                until read -t1 ret; do
                    print -Pn "%S%11F%{.%}%s%f" >&2
                done
                exit "$ret"
            }
        } 3>&1))


    # Maninpulate remote file paths to match the local machine directory
    local_file_path=($(for i in "${bison_remote_files[@]}"; do
                           echo $i |
                               gsed -E "s|/projects/bison/git/bison_[0-9]{8}|$HOME/Documents/projects/bison|g"
                       done
                     ))

    # Loop through remote and local and show where they will be placed
    for ((i=1; i<=${#bison_remote_files[@]}; i++)); do
        print -P "\u251C\U2500%B%1F%{Remote File ->%}%b%f ${bison_remote_files[i]}"
        print -P "\u251C\U2500%B%10F%{Local File  ->%}%b%f ${local_file_path[i]}"

        if [[ $i -lt ${#bison_remote_files[@]} ]]; then
            print -Pn "\U2502\n"
        else
            print -Pn "\U2514\U2500\U2504\U27E2\n"
        fi
    done

# If it's not a dry run, grab all the files using scp
# This is the part I am stuck...
# All my defined variables are un-run in the scope above
# How do I craft a function (or something else) so I don't have to do all the above all over again?    
else
    printf "${YELLOW}Fetching Data from ${NC}(${GREEN}${bison_latest_run}${NC})${YELLOW}...${NC}\n"

    for ((i=0; i<${#NEW_RFILEP[@]}; i++)); do

        scp -qp mcdodyla@falcon1:"${NEW_RFILEP[i]}" "${LOCAL_FILEP[i]}"

        # Check if scp was successful, if it was show green.
        if [ ${PIPESTATUS[0]} -eq 0 ]; then      
            printf "${GREEN}File Created/Updated at:${NC} ${LOCAL_FILEP[i]}\n"
        else
            printf "${RED}Error Fetching File:${NC} ${NEW_RFILEP[i]}\n"
        fi
    done
    printf "${YELLOW}Bison Remote Fetch Complete!${NC}\n"
fi

ご覧のとおり、すべてのデータが最初のifステートメントの状況に閉じ込められているため、練習を実行したくない場合は、すべてのコードを再実行する必要があります。 bash / zshは実際に配列を返さないので、このコードをどのようにリファクタリングできますか?

編集する:ユースケースの例は次のとおりです。

> bfetch -n "HBEP"

Initiating Dry-Run...

Fetching data from:  /projects/bison/git/bison_20190827
├─Remote File -> /projects/bison/git/bison_20190827/assessment/LWR/validation/HBEP/analysis/BK370/HBEP_BK370_out.csv
├─Local File  -> /Users/mcdodj/Documents/projects/bison/assessment/LWR/validation/HBEP/analysis/BK370/HBEP_BK370_out.csv
├─Remote File -> /projects/bison/git/bison_20190827/assessment/LWR/validation/HBEP/analysis/BK363/HBEP_BK363_out.csv
├─Local File  -> /Users/mcdodj/Documents/projects/bison/assessment/LWR/validation/HBEP/analysis/BK363/HBEP_BK363_out.csv
├─Remote File -> /projects/bison/git/bison_20190827/assessment/LWR/validation/HBEP/analysis/BK365/HBEP_BK365_out.csv
├─Local File  -> /Users/mcdodj/Documents/projects/bison/assessment/LWR/validation/HBEP/analysis/BK365/HBEP_BK365_out.csv

ベストアンサー1

わからないzsh。しかし:

stderr1)まず、すべての「セッション」印刷ドアが「ではなく」に移動することを確認してくださいstdout。例:

print -Pn "\n%S%11F%{Initiating Dry-Run%}%s%f" >&2

他にもたくさんあります。

2)彼らはあなたのscp声明を実行せず、例えば次のように実行します。printfstdout

printf 'scp -qp mcdodyla@falcon1:"%s" "%s"\n' "${NEW_RFILEP[i]}"  "${LOCAL_FILEP[i]}"

これには以下が含まれます。みんなcp、、などファイルシステムを変更するステートメントですrm。あなたのスクリプトを簡単に調べた結果、これが私を驚かせた唯一のものです。しかし、あなたはあなたのコードを私よりもよく知っています。rsyncmkdirtouchscp

コードを再確認し、すべてのfs修正(「元に戻すことはできません」)コマンドが「s」printfに変換されていることを3回確認してください。あなたはそれのどれも見逃したくありません。

スクリプトを正しく変換したかどうかをテストするには、スクリプトを実行して削除しますstderr

./myscript 2>/dev/null

stdoutこれはスクリプトにのみ表示する必要があります。

あなたは保証する必要がありますみんな出力は有効なシェル構文です。 すべての情報メッセージはに送信され、stderrすべての「対処」の説明はprintfに送信される必要がありますstdout。それでも一部の情報メッセージがスクリプトに漏れている場合は、戻ってstdoutスクリプトを再編集し、印刷ステートメントがリダイレクトされていることを確認してください>&2

stderr情報メッセージをに送信し、実際の操作をに送信したことを明確に証明すると、stdout変換は完了です。

テスト実行を実行するには、次のスクリプトを実行します。

./myscript

実際に作業を実行するには、スクリプトを再実行してstdoutシェルにパイプします。

./myscript | zsh -v

おすすめ記事