কমান্ড ফাঁকা স্ট্রিং আউটপুট দিলে আমি কীভাবে পরীক্ষা করতে পারি?
ifne
। joeyh.name/code/moreutils
কমান্ড ফাঁকা স্ট্রিং আউটপুট দিলে আমি কীভাবে পরীক্ষা করতে পারি?
ifne
। joeyh.name/code/moreutils
উত্তর:
পূর্বে, প্রশ্নটি জিজ্ঞাসা করেছিল যে ডিরেক্টরিতে ফাইল রয়েছে কিনা তা পরীক্ষা করে দেখুন। নিম্নলিখিত কোডটি এটি অর্জন করে তবে আরও ভাল সমাধানের জন্য আরএসপির উত্তর দেখুন ।
কমান্ড না আসতে মান - তারা তাদের আউটপুট। আপনি কমান্ড প্রতিস্থাপন ব্যবহার করে এই আউটপুট ক্যাপচার করতে পারেন ; যেমন $(ls -A)
। আপনি এইভাবে বাশ-নন-খালি স্ট্রিংয়ের জন্য পরীক্ষা করতে পারেন:
if [[ $(ls -A) ]]; then
echo "there are files"
else
echo "no files found"
fi
দ্রষ্টব্য যে আমি এর -A
পরিবর্তে ব্যবহার করেছি -a
, যেহেতু এটি প্রতীকী বর্তমান ( .
) এবং পিতামাত ( ..
) ডিরেক্টরি এন্ট্রি বাদ দেয় ।
দ্রষ্টব্য: মন্তব্যে উল্লিখিত হিসাবে, কমান্ড প্রতিস্থাপনটি নতুন লাইনের অনুসরণ করে না । সুতরাং, যদি কমান্ডটি কেবলমাত্র নতুন লাইনের আউটপুট দেয় তবে বিকল্পটি কিছুই গ্রহণ করবে না এবং পরীক্ষাটি মিথ্যা হিসাবে প্রত্যাবর্তন করবে। খুব অসম্ভব, যদিও উপরের উদাহরণে এটি সম্ভব, যেহেতু একটি একক নতুন লাইন একটি বৈধ ফাইলের নাম! এই উত্তর আরও তথ্য ।
আপনি যদি কমান্ডটি সফলভাবে সমাপ্ত হয়েছে কিনা তা পরীক্ষা করতে চান, আপনি পরিদর্শন করতে পারবেন $?
, যাতে শেষ কমান্ডের প্রস্থান কোড রয়েছে (সাফল্যের জন্য শূন্য, ব্যর্থতার জন্য শূন্য নয়)। উদাহরণ স্বরূপ:
files=$(ls -A)
if [[ $? != 0 ]]; then
echo "Command failed."
elif [[ $files ]]; then
echo "Files found."
else
echo "No files found."
fi
আরও তথ্য এখানে ।
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then ...; fi
আমার আসলটি উন্নত করার জন্য একটি পরামর্শের জন্য নেটজকে ধন্যবাদ :if [[ $(ls -A | wc -c) -ne 0 ]]; then ...; fi
এটি একটি পুরানো প্রশ্ন তবে আমি কমপক্ষে দুটি জিনিস দেখছি যার কিছুটা উন্নতি বা কমপক্ষে কিছু স্পষ্টতা দরকার।
প্রথম সমস্যাটি আমি দেখতে পাচ্ছি যে এখানে প্রদত্ত বেশিরভাগ উদাহরণগুলি কেবল কাজ করে না । তারা ls -al
এবং ls -Al
কমান্ডগুলি ব্যবহার করে - উভয়ই ফাঁকা ডিরেক্টরিতে ফাঁকা স্ট্রিং আউটপুট দেয়। এই উদাহরণগুলি সর্বদা জানায় যে কোনও ফাইল নেই এমনকী ফাইল রয়েছে ।
সেই কারণে আপনার কেবলমাত্র ব্যবহার করা উচিত ls -A
- কেন যে কেউ -l
যদি কোনও আউটপুট থাকে বা না হয়, তবে পরীক্ষা করতে চাইলে যে কোনও সুইচ যার অর্থ "দীর্ঘ তালিকার বিন্যাসটি ব্যবহার করুন" কেন ব্যবহার করতে চাইবে?
সুতরাং এখানে বেশিরভাগ উত্তর কেবল ভুল।
দ্বিতীয় সমস্যাটি হ'ল কিছু উত্তর সঠিকভাবে কাজ করার সময় (সেগুলি না ব্যবহার ls -al
বা ls -Al
কিন্তু ls -A
পরিবর্তে) তারা সব ভালো কিছু করতে:
পরিবর্তে আমি যা করার পরামর্শ দেব তা হ'ল:
using head -c1
উদাহরণস্বরূপ, পরিবর্তে:
if [[ $(ls -A) ]]
আমি ব্যবহার করব:
if [[ $(ls -A | wc -c) -ne 0 ]]
# or:
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]
পরিবর্তে:
if [ -z "$(ls -lA)" ]
আমি ব্যবহার করব:
if [ $(ls -lA | wc -c) -eq 0 ]
# or:
if [ $(ls -lA | head -c1 | wc -c) -eq 0 ]
ইত্যাদি।
ছোট আউটপুটগুলির ক্ষেত্রে এটি সমস্যা নাও হতে পারে তবে বড় আউটপুটগুলির জন্য পার্থক্যটি উল্লেখযোগ্য হতে পারে:
$ time [ -z "$(seq 1 10000000)" ]
real 0m2.703s
user 0m2.485s
sys 0m0.347s
এর সাথে তুলনা করুন:
$ time [ $(seq 1 10000000 | wc -c) -eq 0 ]
real 0m0.128s
user 0m0.081s
sys 0m0.105s
এবং আরও ভাল:
$ time [ $(seq 1 10000000 | head -c1 | wc -c) -eq 0 ]
real 0m0.004s
user 0m0.000s
sys 0m0.007s
উইল ভসডেনের উত্তর থেকে আপডেট হওয়া উদাহরণ:
if [[ $(ls -A | wc -c) -ne 0 ]]; then
echo "there are files"
else
echo "no files found"
fi
নেটজের পরামর্শের পরে আবার আপডেট হয়েছে :
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then
echo "there are files"
else
echo "no files found"
fi
জেকনফায়ার দ্বারা অতিরিক্ত আপডেট :
grep
কোনও মিল না থাকলে ব্যর্থতার সাথে প্রস্থান করবেন। সিনট্যাক্সটি কিছুটা সহজ করার জন্য আমরা এর সুবিধা নিতে পারি:
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
আপনি যে কমান্ডটি পরীক্ষা করছেন তা যদি কোনও শ্বেতস্পেস আউটপুট করতে পারে যা আপনি খালি স্ট্রিং হিসাবে বিবেচনা করতে চান তবে তার পরিবর্তে:
| wc -c
আপনি ব্যবহার করতে পারেন:
| tr -d ' \n\r\t ' | wc -c
বা সাথে head -c1
:
| tr -d ' \n\r\t ' | head -c1 | wc -c
বা এই জাতীয় কিছু।
প্রথমে একটি কমান্ড ব্যবহার করুন যা কাজ করে ।
দ্বিতীয়ত, র্যামে অপ্রয়োজনীয় স্টোরিং এবং সম্ভাব্য বিশাল ডেটা প্রক্রিয়াকরণ এড়ান।
উত্তরটি নির্দিষ্ট করে দেয় না যে আউটপুট সর্বদা ছোট থাকে তাই বড় আউটপুট হওয়ার সম্ভাবনাটিও বিবেচনা করা দরকার।
[[ $(... | head -c | wc -c) -gt 0 ]]
বা [[ -n $(... | head -c1) ]]
আরও ভাল কারণ wc -c
কমান্ডের পুরো আউটপুট গ্রাস করতে হবে।
if [ -z "$(ls -lA)" ]; then
echo "no files found"
else
echo "There are files"
fi
এটি কমান্ডটি চালাবে এবং ফিরে আউটপুট (স্ট্রিং) এর একটি শূন্য দৈর্ঘ্য রয়েছে কিনা তা পরীক্ষা করবে। আপনি অন্যান্য পতাকাগুলির জন্য 'পরীক্ষা' ম্যানুয়াল পৃষ্ঠাগুলি পরীক্ষা করতে চাইতে পারেন ।
যে আর্গুমেন্টটি যাচাই করা হচ্ছে তার চারপাশে "" ব্যবহার করুন, অন্যথায় খালি ফলাফলের ফলে সিনট্যাক্স ত্রুটি হবে কারণ সেখানে দ্বিতীয় তর্ক (পরীক্ষা করার জন্য) দেওয়া হয়নি!
দ্রষ্টব্য: যে ls -la
সর্বদা ফিরে আসে .
এবং ..
তাই এটি ব্যবহার করে কার্যকর হবে না, দেখুন ম্যানুয়াল পৃষ্ঠাগুলি । তদতিরিক্ত, যদিও এটি সুবিধাজনক এবং সহজ বলে মনে হচ্ছে, আমি মনে করি এটি সহজেই ভেঙে যাবে। একটি ছোট স্ক্রিপ্ট / অ্যাপ্লিকেশন লেখা যা ফলাফলের উপর নির্ভর করে 0 বা 1 প্রদান করে তা অনেক বেশি নির্ভরযোগ্য!
$(
ব্যাককোটের পরিবর্তে ব্যবহার করতে পছন্দ করতে পারেন , কারণ $(
নীড় আরও ভাল
যারা একটি মার্জিত, বাশ সংস্করণ-স্বাধীন সমাধান চান (আসলে অন্যান্য আধুনিক শেলগুলিতে কাজ করা উচিত) এবং যারা দ্রুত কাজের জন্য ওয়ান-লাইনার ব্যবহার করতে পছন্দ করেন তাদের জন্য। আমরা এখানে!
ls | grep . && echo 'files found' || echo 'files not found'
(উল্লিখিত মতামতগুলির মধ্যে একটি হিসাবে নোট করুন, ls -al
এবং বাস্তবে, ন্যায়বিচার -l
এবং -a
সমস্ত কিছু প্রত্যাবর্তন করবে, তাই আমার উত্তরে আমি সহজ ব্যবহার করিls
grep -q ^
পরিবর্তে ব্যবহার করেন তবে নিউলাইন অক্ষরগুলিও মিলবে এবং গ্রেপ স্ট্যান্ডার্ড আউটপুটে কোনও কিছুই মুদ্রণ করবে না। তদতিরিক্ত, এটির ইনপুট স্ট্রিমটি শেষ হওয়ার অপেক্ষা না করে কোনও ইনপুট পাওয়ার সাথে সাথেই এটি প্রস্থান করবে।
ls -A
আপনি যদি ডট-ফাইলগুলি (বা ডিরেক্টরিগুলি) অন্তর্ভুক্ত করতে চান তবে এর সাথে শুরু করা উচিত
-z string
True if the length of string is zero.
-n string
string
True if the length of string is non-zero.
আপনি শর্টহ্যান্ড সংস্করণ ব্যবহার করতে পারেন:
if [[ $(ls -A) ]]; then
echo "there are files"
else
echo "no files found"
fi
string
কেবল একটি প্রতিশব্দ -n string
।
জন লিন মন্তব্য হিসাবে, ls -al
সর্বদা আউটপুট (জন্য .
এবং ..
)। আপনি ls -Al
এই দুটি ডিরেক্টরি এড়াতে চান ।
আপনি উদাহরণস্বরূপ কমান্ডের আউটপুটটিকে শেল ভেরিয়েবলের মধ্যে রাখতে পারেন:
v=$(ls -Al)
একটি পুরানো, অ-বাসা বাঁধার যোগ্য, স্বরলিপিটি
v=`ls -Al`
তবে আমি বাসা বাঁধার স্বরলিপি পছন্দ করি $(
...)
সেই পরিবর্তনশীলটি খালি না থাকলে আপনি পরীক্ষা করতে পারেন
if [ -n "$v" ]; then
echo there are files
else
echo no files
fi
এবং আপনি উভয় হিসাবে একত্রিত করতে পারে if [ -n "$(ls -Al)" ]; then
আমি অনুমান করছি আপনি ls -al
কমান্ডের আউটপুট চান , সুতরাং ব্যাশে আপনার মতো কিছু হবে:
LS=`ls -la`
if [ -n "$LS" ]; then
echo "there are files"
else
echo "no files found"
fi
ls
কখনই কার্যকর হয় না। আপনি কেবল ভেরিয়েবলের সম্প্রসারণটি LS
খালি নয় কিনা তা পরীক্ষা করে দেখুন ।
-a
সুইচ কোনো বিষয়বস্তু নেই আর ফেরত আসবে না (ফাইল আছে থাকুক বা না থাকুক অর্থাত, এতে এমন সব সামগ্রী আসতে হবে), যেহেতু সবসময়ই অন্তর্নিহিত .
এবং ..
ডিরেক্টরি উপস্থিত।
এখনও অবধি দেওয়া সমস্ত উত্তর কমান্ডগুলির সাথে ডিল করে যা একটি খালি স্ট্রিংকে সমাপ্ত করে এবং আউটপুট দেয়।
বেশিরভাগ নিম্নলিখিত সংবেদনগুলিতে ভগ্ন:
yes
)।সুতরাং এই সমস্ত সমস্যা সমাধানের জন্য, এবং নিম্নলিখিত প্রশ্নের দক্ষতার উত্তর দিতে,
কমান্ড ফাঁকা স্ট্রিং আউটপুট দিলে আমি কীভাবে পরীক্ষা করতে পারি?
তুমি ব্যবহার করতে পার:
if read -n1 -d '' < <(command_here); then
echo "Command outputs something"
else
echo "Command doesn't output anything"
fi
এছাড়াও আপনি একটি কমান্ড একটি প্রদত্ত সময়ের মধ্যে একটি খালি স্ট্রিং আউটপুট কিনা, ব্যবহার পরীক্ষা হিসেবে তাই কিছু সময় সমাপ্ত যোগ করতে পারেন read
এর -t
বিকল্প। যেমন, 2.5 সেকেন্ডের সময়সীমা জন্য:
if read -t2.5 -n1 -d '' < <(command_here); then
echo "Command outputs something"
else
echo "Command doesn't output anything"
fi
লক্ষ্য। যদি আপনি মনে করেন যে আপনাকে কোনও কমান্ডটি একটি শূন্য ফাঁকা স্ট্রিং আউটপুট দেয় কিনা তা নির্ধারণ করতে হবে, আপনার খুব সম্ভবত একটি এক্সওয়াই সমস্যা আছে।
seq 1 10000000
, seq 1 20
, এবং printf""
)। একমাত্র ম্যাচআপ যা এই পঠন পদ্ধতিটি জিতেনি তা ছিল -z "$(command)"
খালি ইনপুটটির সাথে যোগাযোগ করা। তারপরেও এটি প্রায় 10-15% হারায়। তারা প্রায় কাছাকাছি বিরতি বলে মনে হচ্ছে seq 1 10
। নির্বিশেষে, ইনপুট আকারটি বাড়ার সাথে সাথে -z "$(command)"
পদ্ধতির এত ধীর হয়ে যায় যে আমি কোনও পরিবর্তনশীল-আকারের ইনপুটটির জন্য এটি ব্যবহার করা এড়াতে চাই।
এখানে একটি বিকল্প পন্থা যা কিছু কমান্ডের std-out এবং std-err কে একটি অস্থায়ী ফাইল লিখে এবং তারপরে সেই ফাইলটি খালি কিনা তা পরীক্ষা করে দেখুন। এই পদ্ধতির একটি সুবিধা হ'ল এটি উভয় আউটপুট ক্যাপচার করে, এবং সাব-শেল বা পাইপ ব্যবহার করে না। এই পরবর্তী দিকগুলি গুরুত্বপূর্ণ কারণ তারা ট্র্যাশিং ব্যাশ প্রস্থান হ্যান্ডলিংয়ের সাথে হস্তক্ষেপ করতে পারে (যেমন এখানে )
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"
কখনও কখনও আপনি আউটপুটটি সংরক্ষণ করতে চান, যদি এটি খালি না থাকে তবে এটি অন্য কমান্ডে প্রেরণ করতে পারেন। যদি তা হয় তবে আপনি এর মতো কিছু ব্যবহার করতে পারেন
list=`grep -l "MY_DESIRED_STRING" *.log `
if [ $? -eq 0 ]
then
/bin/rm $list
fi
এইভাবে, rm
তালিকাটি খালি থাকলে কমান্ডটি স্থগিত হবে না।