シェルスクリプトで1つの操作を完了した後、変数に別の値をどのように割り当てますか?

シェルスクリプトで1つの操作を完了した後、変数に別の値をどのように割り当てますか?

ディレクトリが存在することを確認し、名前/パスに基づいてその下のすべてのコンテンツを圧縮するスクリプトを作成しようとしています。

私が行くことができる最も遠いところは——

#!/system/bin/sh -xv

Z="$PWD/../WorkingDir";
T='320';
F='480';
I='540';
D='dark';
L='light';
P='play';

cd $Z;

if [ -d $T/$D ]; then
    R=""$T"_"$D".zip";
else
    if [ -d $T/$L ]; then
        R=""$T"_"$L".zip";
    else
        R="file.zip";
    fi
fi;

for dir in */*/; do
    #Skip directories where the zip already exists
    [ -e "$dir"/"$R" ] || 
    ( cd -- "$dir" && zip -0rq "$R" .)
done

しかし、これが起こりました -

#!/system/bin/sh -xv
...
.
.
if [ -d $T/$D ]; then
    R=""$T"_"$D".zip";
else
    if [ -d $T/$L ]; then
        R=""$T"_"$L".zip";
    else
        R="file.zip";
    fi
fi;
+ [ -d 320/dark ]
+ R=320_dark.zip

for dir in */*/; do
    #Skip directories where the zip already exists
    [ -e "$dir"/"$R" ] ||
    ( cd -- "$dir" && zip -0rq "$R" .)
done
+ [ -e 320/dark//320_dark.zip ]
+ cd -- 320/dark/
+ zip -0rq 320_dark.zip .
+ [ -e 320/light//320_dark.zip ]
+ cd -- 320/light/
+ zip -0rq 320_dark.zip .
.
.
...and so on..

各ファイルの名前は同じです(320_dark.zipこの場合)。各圧縮ファイルがフォルダ名/パスによって異なることを望みます。

私は思った -

+ [ -d 320/dark ]
+ R=320_dark.zip

- 毎回すべてのフォルダを変更します。320_light.zipフォルダパスがある必要があるように320/light

したがって、出力の最後の部分は -

+ [ -e 320/dark//320_dark.zip ]
+ cd -- 320/dark/
+ zip -0rq 320_dark.zip .
+ [ -e 320/light//320_light.zip ]
+ cd -- 320/light/
+ zip -0rq 320_light.zip .

ベストアンサー1

一貫性のために、単一の文字変数を削除してアーカイブの場所を変更することをお勧めします。

#!/system/bin/sh -xv

cd "$PWD/../WorkingDir"

compress() {
    # Detect only known dir names, convert slash to underscore
    local arch="$(echo $1 | sed -rne '/320\/(light|dark)/s@/@_@gp')"

    # Set a default value to the variable
    : ${arch:=file}

    # Only create a ZIP archive if not present in the parent directory
    # Note $PWD is evaluated *before* cd
    [ -f "${arch}.zip" ] || ( cd -- $1 && zip -0rq "${PWD}/${arch}.zip ." )
}

for dir in */*/; do
    compress $dir
done

その行を変更して、sed「既知のディレクトリ名」を追加します。


編集する:OPの要求に応じて説明を追加します。

ループが新しいディレクトリを見つけるたびに、スクリプトはディレクトリを圧縮する前に条件を確認しますfor。変数も削除されます。コードを分析してみましょう。

メインループ

cd "$PWD/../WorkingDir"

for dir in */*/; do     # Ensures to select only directories
    compress $dir       # compress runs some checks prior to compressing
done

これについてはあまり言うことはありません。

compressルーチン

local arch="$(echo $1 | sed -rne '/320\/(light|dark)/s@/@_@gp')"

$1compressedつまり、チェックして圧縮するディレクトリに渡されるパラメータです。sedまず、('/320\/(light|dark)/')パスが次の形式であることを確認してください。

320/light
320/dark

そして、スラッシュが下線に変換されたパスを返します's@/@_@g'。読みやすさを高め、スラッシュがエスケープされないようにするには、at記号を区切り記号として使用します。他の有効な記号は's:/:_:g'or's#/#_#g'またはclassicです's/\//_/g'。変換したいスラッシュをエスケープするためにバックスラッシュを使用する方法に注意してください。後者の形式が読みにくいと思います。

;pで使用される末尾がsed -n特別な場合、後者のオプションは「p一致するものが見つからない限り(スラッシュで囲まれている場合など)、何もエコーしないでください。»。したがって、archスラッシュを含むパスは下線に変換されます。そして、もし320\/(light|dark)パスで正規表現を見つけます。それ以外の場合は、何もエコーせずにarch空の変数を形成します。

Optionは、より読みやすい標準正規表現の使用を知らせる-r便利な方法です。sedそれ以外の場合は、角かっことパイプ文字をエスケープする必要があります。私は'/320\/(light|dark)/s@/@_@gp'orよりも読みやすいと思います。'/320\/\(light\|dark\)/s@/@_@gp''/320\/\(light\|dark\)/s/\//_/gp'

: ${arch:=file}

行が空の場合、archデフォルト値は「file」に設定されます。この奇妙な設定は、単独${arch:=file}で設定すると構文エラーが発生するため必要です。コロンはシェルに何もせず、空の場合は:値を割り当てるように指示します。arch

    [ -f "${arch}.zip" ] || ( cd -- $1 && zip -0rq "${PWD}/${arch}.zip ." )

ここでは、電子が長さ0のファイルも確認するため、-fnotを使用しました。-eテストはZIPアーカイブが存在する場合にのみ成功します。そして長さがゼロではありません。

親(またはスクリプトの現在の)ディレクトリまたはサイズがnullの場合、スクリプトは引数として渡されたディレクトリを変更しcompressてその内容を圧縮するサブシェルを作成します。変数$1$PWDが評価されます。今後サブシェルは、初期バージョンの親ディレクトリ$PWDと同じコマンドを実行します。$Z

フィルタ拡張

方法は次のとおりですsed

sed -rne '/320\/(light|dark|play)/s@/@_@gp'

ディレクトリ名を確認してください。

320/light
320/dark
320/play

また、9つの組み合わせまたはより一般的な形式(すべての数字の後にスラッシュと「1」が付く)を/(320|480|540)\/(light|dark|play)/提供すると考えることもできます。/[0-9]+\/(light|dark|play)/「、」暗い「そして」遊ぶ)または偶数/[0-9]+\/\w+/(スラッシュと単語の後に続くランダムな数字、別名[A-Za-z0-9_]+)。これは、フィルタをどれほど厳しくまたは広く設定したいかによって異なります。

おすすめ記事