コマンドラインオプションが停止し、変数のデフォルト値を設定しないBashスクリプト

コマンドラインオプションが停止し、変数のデフォルト値を設定しないBashスクリプト

私はbashスクリプトに最初に触れましたが、bashのコマンドライン機能も完全に最初に触れました。ユーザーがコードを直接編集したい場合は、コマンドライン引数と連携して変数値を手動で設定するスクリプトを試しました。

一般的なアイデアは次のとおりです。

  • さまざまな機能のコマンドラインパラメータを定義するには、while/case/getopt構造体を使用してください。
  • そのケース内で各オプションの変数値を設定します。
  • 後でif条件を使用して、コマンドライン引数が実際に指定されていることを確認してください。
  • それ以外の場合、その値はデフォルトのパラメータに設定されます。

このように、myscript.sh -i somestringif ステートメントで -i に関連する変数を使用するか、手動で設定することができます。これは単に./myscript.sh

私は私のコードのif状況が実際に何もしないか、少なくとも私が望むことをしないことを発見しました。コマンドライン引数なしでスクリプトを実行し、ifケースで設定する必要があるデフォルト値をエコーすると、その値は空になります。

これは、その変数がまだ何も設定されていないため、スクリプトの後半のforループが機能しないことを意味します。スクリプトが停止する行は次のとおりです。 slurm_file_string=$(cat $slurm_template_file | sed "s/INPUT_FILE/$gs_file/")

それで、私が達成したいことを達成する方法と、この「詰まった問題」を解決する方法がわかりません。 if状況の内部のデフォルト値が実際に何をするようにif状況を何とか変更する必要がありますが、どうすればよいかわかりません。

これは私のコードです。

#!/bin/bash

# TODO: 
    # Need to figure out if I can launch all slurm jobs with "&" and let slurm handle the rest.
    # Add scratch removal logic to slurm file template. Makes more sense to do it per run in the file that actually runs gaussian.
    # Add commandline options for:
        # input folder (-i) 
        # verbose mode (-v)
        # extension name (-x)
        # slurm template name (-t)
    # Define function be_verbose() which wraps the logic for printing additional info if -v is set to true.

# INFO: Script for running a batch of gaussian jobs using the SLURM scheduler.
    # General program flow: 
        # The script finds all gaussian input files in inps_folder (needs to be manually specified)
            # The input files are identified by the file extension in "extension"
        # The script iterates over all gaussian input files.
            # For each file a slurm file is created based on the template: submit_gaussian_template.slurm
            # Inside the template the string "INPUT_FILE" is replaced by the current input file.
            # The new slurm file is copied to the input files folder
            # The script changes directories to the common pwd of the slurm file and gaussian input file
            # The slurm file is executed and then the next iteration starts.
                # The cleanup is handeled by the shell code inside the slurm file (deleting temp files from /scratch)
            
# IMPORTANT:
    # This script is designed for a certain folder structure.
    # It is required that all your gaussian input files are located in one directory.
    # That folder must be in the same dir as this script.
    # There must be a template slurm file in the directory of this script
    # There must be a string called INPUT_FILE inside the template slurm file 
################################################################################################################################################



# this implements command line functionality. If you do not wish to use them, look for MANUAL_VARS_SPEC below to specify your variables that way.
while getopts "i:vx:t:" opt; do
    case $opt in
        i)
            inps_folder="$OPTARG"
            ;;
            v)
            verbose=true
        ;;
        x)
        extension="$OPTARG"
        echo "$extension"
        ;;
        t)
        slurm_template_file="$OPTARG"
        ;;
        \?)
        echo "Usage: $0 [-i input_folder] [-s value_s] [-k value_k]"
        exit 1
        ;;
    esac
done


# MANUAL_VARS_SPEC: Change the varibles to the appropriate values if you do not wish to use the comman line options.
# These are essentially the default settings of the script.

# folder for input files
if [ -n "$inps_folder" ]; then # "if the commandline option is an empty string (not set), set the variable to this value."
    inps_folder="testinps"
fi

# verbose mode
if [ -n "$verbose" ]; then
    verbose=0
fi

# file extension of your gaussian input files
if [ -n "$extension" ]; then
    echo "AFASGSG"
    extension="gin"
fi

# slurm template file name
if [ -n "$slurm_template_file" ]; then
    slurm_template_file="submit_gaussian_template.slurm"
fi




# HELPER FUNCTIONS
function be_verbose(){
    local print_string="$1" # set the first argument provided to the funtion to the local var "print_string".
    if [ $verbose = true ]; then
        echo "$print_string"
    fi
}

echo "$inps_folder"
echo "$verbose"
echo "$extension"
echo "$slurm_template_file"


#### START OF MAIN LOOP.
files="${inps_folder}/*.${extension}" # iteratable for all gaussian input files.

for file in $files; do
    gs_file=$(basename $file) # get the file without the preceeding path
    gs_file_name="${gs_file%.*}" # get the file name without the extension
    
    # Make a new slurm file for the current job based on the template slurm file in the pwd.
    slurm_file_string=$(cat $slurm_template_file | sed "s/INPUT_FILE/$gs_file/") # get template and replace INPUT_FILE with gaussian input file. FAIL!!!!
    slurm_file="${gs_file_name}.slurm"
    echo "$slurm_file_string" > "$slurm_file" # write the string of the new slurm file to a new file
    mv "$slurm_file" "${inps_folder}/${slurm_file}" # move the new slurm file to the inps_folder

    cd "$inps_folder" # change directories so that slurm files can be executed
    echo "Is running ${gs_file}" #PUT HERE WHATEVER THE COMMAND FOR RUNNIGN A SLURM FILE IS &
    cd ..
done

どんな意見でもよろしくお願いします。

答え1

一般に、問題を実証するのに十分な「検証可能な最小限のコード例」があれば、助けを与える方が簡単です。しかし、ここで私は問題を見ることができると思います。

オプションを解析するときは、次のコードがあります。

while getopts 't:' opt
do
    case "$opt" in
        (t) slurm_template_file="$OPTARG" ;;
    esac
done

しかし後で見ると変数に値がある場合は、固定値に設定します。":

if [ -n "$slurm_template_file" ]
then
    slurm_template_file='submit_gaussian_template.slurm'
fi

変数が設定されていないか空の場合は、デフォルト値を代入する-z代わりにこのコードを使用したかったです。-n

私のアプローチは、変数をデフォルト値に設定し、コマンドラインスイッチを使用してそれを上書きすることでした。また、後で決定を下すために必要な場合、ユーザーに明示的に値を設定するように指示するフラグを設定することもできますが、私の経験ではこれは通常必要ありません。

slurm_template_file='submit_gaussian_template.slurm'
slurm_template_file_isset=false

while getopts 't:' opt
do
    case "$opt" in
        (t)
            slurm_template_file="$OPTARG"
            slurm_template_file_isset=true
            ;;
    esac
done

if "$slurm_template_file_isset"
then
    echo "User overrode the default" >&2
fi
echo "The working value is: $slurm_template_file" >&2

あるいは、コードの上部にデフォルト値を設定し、ジョブ値が設定されていない場合に使用できます。コードは変数名が長いので少し這いますが、注意してみるとより明確になることがあります。

template_default='submit_gaussian_template.slurm'
template=

while getopts 't:' opt
do
    case "$opt" in
        (t)
            template="$OPTARG"
            ;;
    esac
done

if [ -n "$template" ]
then
    echo "User overrode the default: $template" >&2
fi
echo "The working value is: ${template:-$template_default}" >&2

関連情報