リモートサーバーからファイルを検索してローカルコンピュータに戻すスクリプトを作成しています。まず、ツアーを実行してどの文書をインポートする必要があるかを知ることができたらよかったでしょう。
私は現在私が見つけたいくつかのコードのミックスインと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
。しかし:
stderr
1)まず、すべての「セッション」印刷ドアが「ではなく」に移動することを確認してくださいstdout
。例:
print -Pn "\n%S%11F%{Initiating Dry-Run%}%s%f" >&2
他にもたくさんあります。
2)彼らはあなたのscp
声明を実行せず、例えば次のように実行します。printf
stdout
printf 'scp -qp mcdodyla@falcon1:"%s" "%s"\n' "${NEW_RFILEP[i]}" "${LOCAL_FILEP[i]}"
これには以下が含まれます。みんなcp
、、などファイルシステムを変更するステートメントですrm
。あなたのスクリプトを簡単に調べた結果、これが私を驚かせた唯一のものです。しかし、あなたはあなたのコードを私よりもよく知っています。rsync
mkdir
touch
scp
コードを再確認し、すべてのfs修正(「元に戻すことはできません」)コマンドが「s」printf
に変換されていることを3回確認してください。あなたはそれのどれも見逃したくありません。
スクリプトを正しく変換したかどうかをテストするには、スクリプトを実行して削除しますstderr
。
./myscript 2>/dev/null
stdout
これはスクリプトにのみ表示する必要があります。
あなたは保証する必要がありますみんな出力は有効なシェル構文です。 すべての情報メッセージはに送信され、stderr
すべての「対処」の説明はprintf
に送信される必要がありますstdout
。それでも一部の情報メッセージがスクリプトに漏れている場合は、戻ってstdout
スクリプトを再編集し、印刷ステートメントがリダイレクトされていることを確認してください>&2
。
stderr
情報メッセージをに送信し、実際の操作をに送信したことを明確に証明すると、stdout
変換は完了です。
テスト実行を実行するには、次のスクリプトを実行します。
./myscript
実際に作業を実行するには、スクリプトを再実行してstdout
シェルにパイプします。
./myscript | zsh -v
答え2
私はスクリプトに精通しておらず、他のシェルが何をしているのかわかりません。
ただし、最終結果としてすべてのコードを再度繰り返す必要がある場合は、m4などのマクロプロセッサからコードを構築し、m4プロセッサを使用してソースコードを完全なスクリプトに拡張できます。
たとえば、配列なしでアセンブリ言語で書くがアドレスを繰り返す必要がある場合は、固定アドレスにいくつかのマクロ変数を使用してルーチンを一度作成し、m4処理後にマクロファイルに「配列」とforループを定義することもできます。 、1つは完全な複製ソースを持ちます。
たぶんここで同様のことができますか?あるいは、役に立たないアイデアかもしれません。ただ考えです。