Hindari menjalankan skrip jika variabel tidak didefinisikan

18

Saya memiliki skrip seperti:

c=0
for f in */*; do
cp -v "$f" "/myhome/CE$(printf '%0*d' 2 $BATCHNUM)-new-stuctures_extracted/test-$(printf '%0*d' 5 $c)"
c=$((c=c+1))
done

Namun, pengguna harus memberikan BATCHNUM panggilan variabel dan jika tidak saya harus memaksa skrip ini berhenti berjalan. Akan lebih baik jika saya bisa memaksa skrip yang memanggil skrip ini untuk berhenti juga (atau bahkan skrip # 1 yang memanggil skrip # 2 yang memanggil skrip ini).

pengguna40780
sumber

Jawaban:

28

Cara tercepat adalah menambahkan dua baris ini ke awal skrip:

set -u # or set -o nounset
: "$BATCHNUM"

Baris pertama menetapkan nounsetopsi dalam shell yang menjalankan skrip, yang dibatalkan jika Anda mencoba untuk memperluas variabel yang tidak disetel; yang kedua berkembang $BATCHNUMdalam konteks no-op, untuk memicu aborsi sebelum melakukan hal lain.

Jika Anda menginginkan pesan kesalahan yang lebih bermanfaat, Anda bisa menulis:

if [[ -z "$BATCHNUM" ]]; then
    echo "Must provide BATCHNUM in environment" 1>&2
    exit 1
fi

Atau serupa.

Tom Hunt
sumber
18

Di sini Anda ingin memeriksa BATCHNUMdiatur dan tidak nol.

Shell POSIX memberikan Ekspansi Parameter untuk pekerjaan ini. Cukup tambahkan baris ini sebelum menggunakan BATCHNUM:

: "${BATCHNUM:?Variable not set or empty}"

atau lebih baik untuk menetapkan nilai default BATCHNUMjika pengguna tidak memberikannya:

: "${BATCHNUM:=3}"
cuonglm
sumber
4
[ -n "$BATCHNUM" ] || { kill "$PPID"; exit 1; }
#Unless $BATCHNUM is defined and unempty, ask parent process to exit and exit w/ 1

Ini akan bekerja pada bash dan dalam POSIX sh. Saya lebih suka untuk tidak membedakan antara variabel kosong dan variabel tidak terdefinisi (yaitu, saya tidak suka set -u, tapi itu hanya saya).

PSkocik
sumber
2

Garis

if [ -z "$BATCHNUM" ]; then
    exit 2;
fi

periksa kosong $BATCHNUM. Dengan $PPIDAnda dapat melakukan apa pun yang Anda inginkan untuk orang tua Anda ( kill $PPID). Untuk membunuh kakek-nenek Anda, Anda perlu mendapatkan id proses dengan cara lain, seperti melihat data di dalamnya /proc/$PPID.

Namun, jika orang tua Anda meninggal, ia mengirimkan sinyal ( SIGHUP) kepada Anda, jadi Anda harus menjebaknya sebelum mulai membunuh siapa pun:

trap '' SIGHUP

Perbarui: Jika Anda berpikir Anda harus membunuh orang tua Anda, Anda salah melakukannya. Cukup kembalikan kode sandi yang berarti. Skrip induk harus memeriksa kode pengembalian skrip yang dipanggil dan bereaksi sesuai.

Thomas Erker
sumber
1
agak brutal .... :)
user40780
1

Untuk menguji apakah BATCHNUMsudah ditentukan, dan keluar jika tidak:

if [ -n "${BATCHNUM-a}" ]; then
  echo >&2 "Fatal error: BATCHNUM not set"
  exit 2
fi

Jika Anda juga ingin menolak kasing yang BATCHNUMkosong, gunakan ${BATCHNUM:+a}sebagai ganti ${BATCHNUM+a}. Untuk informasi tentang ${VARIABLE+TEXT_IF_NULL}konstruk ekspansi parameter, lihat misalnya manual bash .

Jangan bunuh proses induk. Anda tidak tahu apa proses induknya. Jika beberapa skrip yang memanggil yang ini perlu dibatalkan jika skrip ini batal, buatlah periksa status keluar skrip ini. Misalnya dalam skrip # 2:

script3 || exit $?

atau gunakan set -euntuk membatalkan skrip jika ada perintah yang mengembalikan status kegagalan (bukan nol).

Gilles 'SO- berhenti menjadi jahat'
sumber