Sangat penting untuk menyadari bahwa itu sebenarnya shell yang memperluas foo*ke daftar nama file yang cocok, jadi ada sedikit yang mvbisa dilakukan sendiri.
Masalahnya di sini adalah bahwa ketika gumpalan tidak cocok, beberapa cangkang seperti bash(dan kebanyakan cangkang mirip Bourne lainnya, bahwa perilaku buggy sebenarnya diperkenalkan oleh cangkang Bourne pada akhir 70-an) meneruskan pola kata demi kata ke perintah.
Jadi di sini, ketika foo*tidak cocok dengan file apa pun, alih-alih membatalkan perintah (seperti shell pra-Bourne dan beberapa shell modern lakukan), shell melewati foo*file kata demi kata mv, jadi pada dasarnya meminta mvuntuk memindahkan file yang disebut foo*.
File itu tidak ada. Jika ya, itu akan benar-benar cocok dengan polanya, jadi mvmelaporkan kesalahan. Jika polanya sudah foo[xy], mvbisa saja secara tidak sengaja memindahkan file yang disebut foo[xy]bukan fooxdan fooyfile.
Sekarang, bahkan di shell yang tidak memiliki masalah (pre-Bourne, csh, tcsh, fish, zsh, bash -O failglob), Anda masih akan mendapatkan kesalahan mv foo* ~/bar, tetapi kali ini oleh shell.
Jika Anda ingin menganggapnya bukan kesalahan jika tidak ada file yang cocok foo*dan dalam hal itu, tidak memindahkan apa pun, Anda ingin membuat daftar file terlebih dahulu (dengan cara yang tidak menyebabkan kesalahan seperti dengan menggunakan nullglobopsi beberapa kerang), dan kemudian hanya panggilan mvdaftar tidak kosong.
Itu akan lebih baik daripada menyembunyikan semua kesalahan mv(seperti menambahkan 2> /dev/nullakan) seolah-olah mvgagal karena alasan lain, Anda mungkin masih ingin tahu mengapa.
dalam zsh
files=(foo*(N)) # where the N glob qualifier activates nullglob for that glob
(($#files == 0)) || mv -- $files ~/bar/
Atau gunakan fungsi anonim untuk menghindari penggunaan variabel sementara:
() { (($# == 0)) || mv -- "$@" ~/bar/; } foo*(N)
zshadalah salah satu dari shell yang tidak memiliki bug Bourne dan melaporkan kesalahan tanpa menjalankan perintah ketika glob tidak cocok (dan nullglobopsi belum diaktifkan), jadi di sini, Anda bisa menyembunyikan zshkesalahan dan mengembalikan stderr untuk mvjadi Anda masih akan melihat mvkesalahan jika ada, tetapi bukan kesalahan tentang gumpalan yang tidak cocok:
(mv 2>&3 foo* ~/bar/) 3>&2 2>&-
Atau Anda dapat menggunakan zargsyang juga akan menghindari masalah jika foo*gumpalan akan berkembang menjadi terlalu banyak file.
autoload zargs # best in ~/.zshrc
zargs -r -- foo* -- mv -t ~/bar # here assuming GNU mv for its -t option
Dalam ksh93:
files=(~(N)foo*)
((${#files[#]} == 0)) || mv -- "${files[@]}" ~/bar/
Dalam bash:
bashtidak memiliki sintaks untuk mengaktifkan nullglobsatu bola saja, dan failglobopsi dibatalkan nullglobsehingga Anda akan memerlukan hal-hal seperti:
saved=$(shopt -p nullglob failglob) || true
shopt -s nullglob
shopt -u failglob
files=(foo*)
((${#files[@]} == 0)) || mv -- "${files[@]}" ~/bar/
eval "$saved"
atau mengatur opsi dalam subkulit untuk menyimpan harus menyimpannya sebelum dan mengembalikannya sesudahnya.
(
shopt -s nullglob
shopt -u failglob
files=(foo*)
((${#files[@]} == 0)) || mv -- "${files[@]}" ~/bar/
)
Di yash
(
set -o nullglob
files=(foo*)
[ "${#files[@]}" -eq 0 ] || mv -- "${files[@]}" ~/bar/
)
Di fish
Di shell ikan, perilaku nullglob adalah default untuk setperintah, jadi itu hanya:
set files foo*
count $files > /dev/null; and mv -- $files ~/bar/
POSIXly
Tidak ada nullglobopsi di POSIX shdan tidak ada array selain dari parameter posisi. Ada trik yang dapat Anda gunakan untuk mendeteksi apakah sebuah glob cocok atau tidak:
set -- foo[*] foo*
if [ "$1$2" != 'foo[*]foo*' ]; then
shift
mv -- "$@" ~/bar/
fi
Dengan menggunakan a foo[*]dan foo*glob, kita dapat membedakan antara kasus di mana tidak ada file yang cocok dan yang di mana ada satu file yang disebut foo*(yang set -- foo*tidak bisa dilakukan).
Lebih banyak membaca:
mv foo* ~/bar/ 2> /dev/null?