Bagaimana saya bisa menguji jika suatu perintah menghasilkan string kosong?
ifneuntuk ini. joeyh.name/code/moreutils
Bagaimana saya bisa menguji jika suatu perintah menghasilkan string kosong?
ifneuntuk ini. joeyh.name/code/moreutils
Jawaban:
Sebelumnya, pertanyaannya bertanya bagaimana memeriksa apakah ada file dalam direktori. Kode berikut mencapai itu, tetapi lihat jawaban rsp untuk solusi yang lebih baik.
Perintah tidak mengembalikan nilai - mereka mengeluarkannya. Anda dapat menangkap output ini dengan menggunakan substitusi perintah ; mis $(ls -A). Anda dapat menguji untuk string yang tidak kosong di Bash seperti ini:
if [[ $(ls -A) ]]; then
echo "there are files"
else
echo "no files found"
fi
Perhatikan bahwa saya telah menggunakan -Adaripada -a, karena menghapus entri direktori simbolik ( .) dan parent ( ..).
Catatan: Seperti yang ditunjukkan dalam komentar, substitusi perintah tidak menangkap baris baru . Oleh karena itu, jika perintah hanya menghasilkan baris baru, substitusi akan menangkap apa-apa dan tes akan kembali salah. Meskipun sangat tidak mungkin, ini dimungkinkan dalam contoh di atas, karena satu baris baru adalah nama file yang valid! Informasi lebih lanjut dalam jawaban ini .
Jika Anda ingin memeriksa bahwa perintah selesai dengan sukses, Anda dapat memeriksa $?, yang berisi kode keluar dari perintah terakhir (nol untuk sukses, bukan nol untuk kegagalan). Sebagai contoh:
files=$(ls -A)
if [[ $? != 0 ]]; then
echo "Command failed."
elif [[ $files ]]; then
echo "Files found."
else
echo "No files found."
fi
Info lebih lanjut di sini .
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then ...; fiTerima kasih kepada netj
untuk saran untuk meningkatkan sumber asli saya:if [[ $(ls -A | wc -c) -ne 0 ]]; then ...; fi
Ini adalah pertanyaan lama tetapi saya melihat setidaknya dua hal yang perlu perbaikan atau setidaknya beberapa klarifikasi.
Masalah pertama yang saya lihat adalah bahwa sebagian besar contoh yang diberikan di sini tidak berfungsi . Mereka menggunakan perintah ls -aldan ls -Al- keduanya menghasilkan string yang tidak kosong di direktori kosong. Contoh-contoh itu selalu melaporkan bahwa ada file bahkan ketika tidak ada .
Untuk alasan itu Anda hanya perlu menggunakan ls -A- Mengapa ada orang yang ingin menggunakan -lsaklar yang berarti "menggunakan format daftar panjang" ketika semua yang Anda inginkan adalah menguji apakah ada output atau tidak, toh?
Jadi sebagian besar jawaban di sini tidak benar.
Masalah kedua adalah bahwa sementara beberapa jawaban bekerja dengan baik (orang-orang yang tidak menggunakan ls -alatau ls -Altetapi ls -Asebaliknya) mereka semua melakukan sesuatu seperti ini:
Apa yang saya sarankan lakukan adalah:
using head -c1Jadi misalnya, alih-alih:
if [[ $(ls -A) ]]
Saya akan menggunakan:
if [[ $(ls -A | wc -c) -ne 0 ]]
# or:
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]
Dari pada:
if [ -z "$(ls -lA)" ]
Saya akan menggunakan:
if [ $(ls -lA | wc -c) -eq 0 ]
# or:
if [ $(ls -lA | head -c1 | wc -c) -eq 0 ]
dan seterusnya.
Untuk output kecil mungkin bukan masalah tetapi untuk output yang lebih besar perbedaannya mungkin signifikan:
$ time [ -z "$(seq 1 10000000)" ]
real 0m2.703s
user 0m2.485s
sys 0m0.347s
Bandingkan dengan:
$ time [ $(seq 1 10000000 | wc -c) -eq 0 ]
real 0m0.128s
user 0m0.081s
sys 0m0.105s
Dan bahkan lebih baik:
$ time [ $(seq 1 10000000 | head -c1 | wc -c) -eq 0 ]
real 0m0.004s
user 0m0.000s
sys 0m0.007s
Contoh yang diperbarui dari jawaban oleh Will Vousden:
if [[ $(ls -A | wc -c) -ne 0 ]]; then
echo "there are files"
else
echo "no files found"
fi
Diperbarui lagi setelah saran oleh netj :
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then
echo "there are files"
else
echo "no files found"
fi
Pembaruan tambahan oleh jakeonfire :
grepakan keluar dengan kegagalan jika tidak ada kecocokan. Kita dapat memanfaatkan ini untuk menyederhanakan sintaksis sedikit:
if ls -A | head -c1 | grep -E '.'; then
echo "there are files"
fi
if ! ls -A | head -c1 | grep -E '.'; then
echo "no files found"
fi
Jika perintah yang Anda uji bisa menghasilkan beberapa spasi putih yang ingin Anda perlakukan sebagai string kosong, maka alih-alih:
| wc -c
Anda bisa menggunakan:
| tr -d ' \n\r\t ' | wc -c
atau dengan head -c1:
| tr -d ' \n\r\t ' | head -c1 | wc -c
atau semacam itu.
Pertama, gunakan perintah yang berfungsi .
Kedua, hindari penyimpanan yang tidak perlu dalam RAM dan pemrosesan data yang berpotensi besar.
Jawabannya tidak menentukan bahwa output selalu kecil sehingga kemungkinan output yang besar perlu dipertimbangkan juga.
[[ $(... | head -c | wc -c) -gt 0 ]]atau [[ -n $(... | head -c1) ]]lebih baik karena wc -charus mengkonsumsi seluruh output dari perintah.
if [ -z "$(ls -lA)" ]; then
echo "no files found"
else
echo "There are files"
fi
Ini akan menjalankan perintah dan memeriksa apakah output (string) yang dikembalikan memiliki panjang nol. Anda mungkin ingin memeriksa halaman manual 'test' untuk flag lainnya.
Gunakan "" di sekitar argumen yang sedang diperiksa, jika tidak, hasil kosong akan menghasilkan kesalahan sintaks karena tidak ada argumen kedua (untuk memeriksa) yang diberikan!
Catatan: yang ls -laselalu kembali .dan ..menggunakan itu tidak akan berfungsi, lihat halaman manual ls . Selain itu, walaupun ini mungkin tampak mudah dan mudah, saya kira itu akan mudah pecah. Menulis skrip / aplikasi kecil yang mengembalikan 0 atau 1 tergantung pada hasilnya jauh lebih dapat diandalkan!
$(daripada backquote, karena $(sarang lebih baik
Bagi mereka yang menginginkan solusi elegan, versi bash-independen (sebenarnya harus bekerja di shell modern lainnya) dan mereka yang suka menggunakan one-liners untuk tugas cepat. Kita mulai!
ls | grep . && echo 'files found' || echo 'files not found'
(perhatikan sebagai salah satu komentar yang disebutkan, ls -aldan pada kenyataannya, hanya -ldan -asemua akan mengembalikan sesuatu, jadi dalam jawaban saya, saya menggunakan sederhanals
grep -q ^sebagai gantinya, karakter baris baru juga akan cocok, dan grep tidak akan mencetak apa pun ke output standar. Selain itu, ia akan keluar segera setelah menerima input apa pun, daripada menunggu aliran inputnya berakhir.
ls -Ajika Anda ingin memasukkan file-file (atau direktori)
-z string
True if the length of string is zero.
-n string
string
True if the length of string is non-zero.
Anda dapat menggunakan versi steno:
if [[ $(ls -A) ]]; then
echo "there are files"
else
echo "no files found"
fi
stringadalah sinonim untuk -n string.
Seperti komentar Jon Lin, ls -alakan selalu menampilkan (untuk .dan ..). Anda ingin ls -Almenghindari dua direktori ini.
Misalnya Anda bisa memasukkan output perintah ke dalam variabel shell:
v=$(ls -Al)
Notasi yang lebih tua, tidak dapat ditumpuk, adalah
v=`ls -Al`
tapi saya lebih suka notasi nestable $(...)
Anda dapat menguji apakah variabel itu tidak kosong
if [ -n "$v" ]; then
echo there are files
else
echo no files
fi
Dan Anda bisa menggabungkan keduanya sebagai if [ -n "$(ls -Al)" ]; then
Saya kira Anda ingin output dari ls -alperintah, jadi dalam bash, Anda akan memiliki sesuatu seperti:
LS=`ls -la`
if [ -n "$LS" ]; then
echo "there are files"
else
echo "no files found"
fi
lstidak pernah dijalankan. Anda hanya memeriksa apakah perluasan variabel LS tidak kosong.
-asaklar tidak akan pernah kembali ada konten (yaitu, itu akan kembali konten apakah ada file atau tidak) karena selalu ada implisit .dan ..hadir direktori.
Inilah solusi untuk kasus yang lebih ekstrem:
if [ `command | head -c1 | wc -c` -gt 0 ]; then ...; fi
Ini akan bekerja
namun,
Semua jawaban yang diberikan sejauh ini berhubungan dengan perintah yang mengakhiri dan menghasilkan string yang tidak kosong.
Sebagian besar rusak dalam pengertian berikut:
yes).Jadi untuk memperbaiki semua masalah ini, dan untuk menjawab pertanyaan berikut secara efisien,
Bagaimana saya bisa menguji jika suatu perintah menghasilkan string kosong?
kamu bisa memakai:
if read -n1 -d '' < <(command_here); then
echo "Command outputs something"
else
echo "Command doesn't output anything"
fi
Anda juga dapat menambahkan beberapa batas waktu sehingga untuk menguji apakah perintah output string yang tidak kosong dalam waktu tertentu, menggunakan read's -tpilihan. Misalnya, untuk batas waktu 2,5 detik:
if read -t2.5 -n1 -d '' < <(command_here); then
echo "Command outputs something"
else
echo "Command doesn't output anything"
fi
Ucapan. Jika Anda merasa perlu menentukan apakah perintah menghasilkan string yang tidak kosong, kemungkinan besar Anda memiliki masalah XY.
seq 1 10000000, seq 1 20, dan printf""). Satu-satunya pertarungan pendekatan baca ini tidak menang adalah dengan -z "$(command)"pendekatan untuk input kosong. Meski begitu, kerugiannya hanya sekitar 10-15%. Mereka tampaknya impas seq 1 10. Terlepas dari itu, -z "$(command)"pendekatannya menjadi sangat lambat ketika ukuran input bertambah sehingga saya menghindari menggunakannya untuk input ukuran variabel.
Berikut adalah pendekatan alternatif yang menulis std-out dan std-err dari beberapa perintah file sementara, dan kemudian memeriksa untuk melihat apakah file itu kosong. Manfaat dari pendekatan ini adalah bahwa ia menangkap kedua output, dan tidak menggunakan sub-shell atau pipa. Aspek-aspek terakhir ini penting karena mereka dapat mengganggu trapping bash exit handling (mis. Di sini )
tmpfile=$(mktemp)
some-command &> "$tmpfile"
if [[ $? != 0 ]]; then
echo "Command failed"
elif [[ -s "$tmpfile" ]]; then
echo "Command generated output"
else
echo "Command has no output"
fi
rm -f "$tmpfile"
Terkadang Anda ingin menyimpan output, jika tidak kosong, untuk meneruskannya ke perintah lain. Jika demikian, Anda bisa menggunakan sesuatu seperti
list=`grep -l "MY_DESIRED_STRING" *.log `
if [ $? -eq 0 ]
then
/bin/rm $list
fi
Dengan cara ini, rmperintah tidak akan hang jika daftar kosong.