যদি একটি কমান্ড একটি ফাঁকা স্ট্রিং আউটপুট দেয় তবে পরীক্ষা করুন


237

কমান্ড ফাঁকা স্ট্রিং আউটপুট দিলে আমি কীভাবে পরীক্ষা করতে পারি?


7
একটি কমান্ড একটি স্ট্রিং ফেরত দেয় না (এটি একটি ছোট পূর্ণসংখ্যার প্রস্থান কোড ফেরত দেয়, সাধারণত সাফল্যের জন্য 0 এবং ব্যর্থতার ক্ষেত্রে 1 বা 2) তবে স্ট্রিংয়ের জন্য এটি কিছু ডেটা আউটপুট দিতে পারে ।
বেসিল স্টারিনকিভিচ

@BasileStarynkevitch এই জিনিস আমি need.I জানা কমান্ড আয় প্রস্থান code.But আমার কমান্ড প্রস্থান কোড সবসময় 0.so আমি আউটপুট নিয়ন্ত্রণ করতে হবে হয়
Barp

1
আপনার কিছু বাশ স্ক্রিপ্টিং টিউটোরিয়ালটি পড়তে হবে tldp.org/LDP/abs/html
বেসাইল স্টারিনকিভিচ

জোয়ে হেস এর জন্য একটি ইউটিলিটি রয়েছে ifnejoeyh.name/code/moreutils
ট্রিপল

উত্তর:


309

পূর্বে, প্রশ্নটি জিজ্ঞাসা করেছিল যে ডিরেক্টরিতে ফাইল রয়েছে কিনা তা পরীক্ষা করে দেখুন। নিম্নলিখিত কোডটি এটি অর্জন করে তবে আরও ভাল সমাধানের জন্য আরএসপির উত্তর দেখুন ।


খালি আউটপুট

কমান্ড না আসতে মান - তারা তাদের আউটপুট। আপনি কমান্ড প্রতিস্থাপন ব্যবহার করে এই আউটপুট ক্যাপচার করতে পারেন ; যেমন $(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

আরও তথ্য এখানে


4
আপনি বাদ দিতে পারেন -n , তাই এটি ঠিক হবেif [[ $(ls -A) ]]; then
ব্যবহারকারী

6
এই পদ্ধতিটি কমান্ডগুলির জন্য মিথ্যা দেয় যা কেবলমাত্র নতুন লাইনের আউটপুট দেয়।
সিরো সান্তিলি 郝海东 冠状 病 六四 事件 法轮功

89

টি এল; ডিআর

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পরিবর্তে) তারা সব ভালো কিছু করতে:

  1. কমান্ড চালান
  2. এটির পুরো আউটপুট র‍্যামে বাফার করুন
  3. আউটপুটটিকে একটি বিশাল একক-লাইনের স্ট্রিংয়ে রূপান্তর করুন
  4. সেই স্ট্রিংটিকে একটি খালি স্ট্রিংয়ের সাথে তুলনা করুন

পরিবর্তে আমি যা করার পরামর্শ দেব তা হ'ল:

  1. কমান্ড চালান
  2. অক্ষরগুলি সংরক্ষণ না করে এর আউটপুটে অক্ষরগুলি গণনা করুন
    • বা আরও ভাল - সর্বাধিক 1 টি চরিত্রের সংখ্যা গণনা করুন using head -c1
      ( নীচের মন্তব্যে এই ধারণাটি পোস্ট করার জন্য নেটজকে ধন্যবাদ )
  3. সেই সংখ্যাটি শূন্যের সাথে তুলনা করুন

উদাহরণস্বরূপ, পরিবর্তে:

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

বা এই জাতীয় কিছু।

সারসংক্ষেপ

  1. প্রথমে একটি কমান্ড ব্যবহার করুন যা কাজ করে

  2. দ্বিতীয়ত, র‍্যামে অপ্রয়োজনীয় স্টোরিং এবং সম্ভাব্য বিশাল ডেটা প্রক্রিয়াকরণ এড়ান।

উত্তরটি নির্দিষ্ট করে দেয় না যে আউটপুট সর্বদা ছোট থাকে তাই বড় আউটপুট হওয়ার সম্ভাবনাটিও বিবেচনা করা দরকার।


3
[[ $(... | head -c | wc -c) -gt 0 ]]বা [[ -n $(... | head -c1) ]]আরও ভাল কারণ wc -cকমান্ডের পুরো আউটপুট গ্রাস করতে হবে।
নেটজ

@ নেটজ এটি খুব ভাল ধারণা। আমার আপডেট হওয়া উত্তরটি দেখুন - আমি আপনার পরামর্শ যুক্ত করেছি। অনেক ধন্যবাদ!
আরএসপি

আউটপুট ধরে রাখা কীভাবে কোনও ধারণা?
fahrradflucht

আমি মনে করি আসল (মাথা ছাড়াই) সাধারণ ক্ষেত্রে ভাল। আউটপুট লেখা শুরু করার সাথে সাথে কমান্ডটি হত্যা করা সবসময় ভাল ধারণা নয়!
stk

@stk বেশিরভাগ প্রোগ্রাম একটি কিল সংকেত পাওয়ার পরে নিরাপদে প্রস্থান করবে।
অস্পষ্ট

40
if [ -z "$(ls -lA)" ]; then
  echo "no files found"
else
  echo "There are files"
fi

এটি কমান্ডটি চালাবে এবং ফিরে আউটপুট (স্ট্রিং) এর একটি শূন্য দৈর্ঘ্য রয়েছে কিনা তা পরীক্ষা করবে। আপনি অন্যান্য পতাকাগুলির জন্য 'পরীক্ষা' ম্যানুয়াল পৃষ্ঠাগুলি পরীক্ষা করতে চাইতে পারেন ।

যে আর্গুমেন্টটি যাচাই করা হচ্ছে তার চারপাশে "" ব্যবহার করুন, অন্যথায় খালি ফলাফলের ফলে সিনট্যাক্স ত্রুটি হবে কারণ সেখানে দ্বিতীয় তর্ক (পরীক্ষা করার জন্য) দেওয়া হয়নি!

দ্রষ্টব্য: যে ls -laসর্বদা ফিরে আসে .এবং ..তাই এটি ব্যবহার করে কার্যকর হবে না, দেখুন ম্যানুয়াল পৃষ্ঠাগুলি । তদতিরিক্ত, যদিও এটি সুবিধাজনক এবং সহজ বলে মনে হচ্ছে, আমি মনে করি এটি সহজেই ভেঙে যাবে। একটি ছোট স্ক্রিপ্ট / অ্যাপ্লিকেশন লেখা যা ফলাফলের উপর নির্ভর করে 0 বা 1 প্রদান করে তা অনেক বেশি নির্ভরযোগ্য!


আপনি $(ব্যাককোটের পরিবর্তে ব্যবহার করতে পছন্দ করতে পারেন , কারণ $(নীড় আরও ভাল
বেসাইল স্টারিনকিভিচ

আপনি ঠিক বলেছেন এগুলি সর্বদা ব্যবহার করা ভাল অনুশীলন, যদিও আমাদের এখানে বাসা বাঁধার দরকার নেই।
ভিগার

23

যারা একটি মার্জিত, বাশ সংস্করণ-স্বাধীন সমাধান চান (আসলে অন্যান্য আধুনিক শেলগুলিতে কাজ করা উচিত) এবং যারা দ্রুত কাজের জন্য ওয়ান-লাইনার ব্যবহার করতে পছন্দ করেন তাদের জন্য। আমরা এখানে!

ls | grep . && echo 'files found' || echo 'files not found'

(উল্লিখিত মতামতগুলির মধ্যে একটি হিসাবে নোট করুন, ls -alএবং বাস্তবে, ন্যায়বিচার -lএবং -aসমস্ত কিছু প্রত্যাবর্তন করবে, তাই আমার উত্তরে আমি সহজ ব্যবহার করিls


5
আপনি যদি এর grep -q ^পরিবর্তে ব্যবহার করেন তবে নিউলাইন অক্ষরগুলিও মিলবে এবং গ্রেপ স্ট্যান্ডার্ড আউটপুটে কোনও কিছুই মুদ্রণ করবে না। তদতিরিক্ত, এটির ইনপুট স্ট্রিমটি শেষ হওয়ার অপেক্ষা না করে কোনও ইনপুট পাওয়ার সাথে সাথেই এটি প্রস্থান করবে।
মর্তেহু

ls -Aআপনি যদি ডট-ফাইলগুলি (বা ডিরেক্টরিগুলি) অন্তর্ভুক্ত করতে চান তবে এর সাথে শুরু করা উচিত
ক্রেলি

13

বাশ রেফারেন্স ম্যানুয়াল

.4.৪ বাশ শর্তাধীন অভিব্যক্তি

-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

1
বন্ধনীতে একটি -z বা -n অনুপস্থিত রয়েছে [[...]]।
71GA

4
@ GA১ গিগা: সম্ভবত এটি উপেক্ষা করা সহজ, তবে আপনি যদি মনোযোগ দিয়ে দেখেন তবে আপনি দেখতে পাবেন যে এটি stringকেবল একটি প্রতিশব্দ -n string
ব্যবহারকারী

10

জন লিন মন্তব্য হিসাবে, 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


5

আমি অনুমান করছি আপনি ls -alকমান্ডের আউটপুট চান , সুতরাং ব্যাশে আপনার মতো কিছু হবে:

LS=`ls -la`

if [ -n "$LS" ]; then
  echo "there are files"
else
  echo "no files found"
fi

এটি কাজ করে না: কমান্ডটি lsকখনই কার্যকর হয় না। আপনি কেবল ভেরিয়েবলের সম্প্রসারণটি LS খালি নয় কিনা তা পরীক্ষা করে দেখুন ।
gniourf_gniourf

1
@gniourf_gniourf - আপনাকে কী এমন ভাবতে বাধ্য করে? ব্যাকটিক জাদুমন্ত্রোচ্চারণ বোঝা যাচ্ছে যে নেতারা যেমন প্রশংসনীয় বা নমনীয় $ () নামে নয়, কিন্তু এটি কাজ করে ...
Tink

-aসুইচ কোনো বিষয়বস্তু নেই আর ফেরত আসবে না (ফাইল আছে থাকুক বা না থাকুক অর্থাত, এতে এমন সব সামগ্রী আসতে হবে), যেহেতু সবসময়ই অন্তর্নিহিত .এবং ..ডিরেক্টরি উপস্থিত।
ক্রেলি

3

আরও চরম মামলার সমাধান এখানে:

if [ `command | head -c1 | wc -c` -gt 0 ]; then ...; fi

এটি কাজ করবে

  • সমস্ত বোর্ন শেল জন্য;
  • যদি কমান্ড আউটপুট সমস্ত শূন্য হয়;
  • আউটপুট আকার নির্বিশেষে দক্ষতার সাথে;

যাহোক,

  • কোনও কিছু আউটপুট হলে কমান্ড বা এর উপ-প্রসেসগুলি হত্যা করা হবে।

1

এখনও অবধি দেওয়া সমস্ত উত্তর কমান্ডগুলির সাথে ডিল করে যা একটি খালি স্ট্রিংকে সমাপ্ত করে এবং আউটপুট দেয়।

বেশিরভাগ নিম্নলিখিত সংবেদনগুলিতে ভগ্ন:

  • কমান্ডগুলি কেবলমাত্র নিউলাইনগুলি আউটপুট দেয় তা তারা সঠিকভাবে মোকাবেলা করে না;
  • কমান্ড আউটপুট নাল বাইট (যদি তারা কমান্ড প্রতিস্থাপন ব্যবহার করে) কমান্ড আউটপুট নাল বাইটগুলি স্পষ্ট করে বাশ≥.৪ থেকে শুরু করে সর্বাধিক ত্রুটি স্প্যাম করবে;
  • বেশিরভাগ সম্পূর্ণ আউটপুট স্ট্রিম স্লার্প করবে, সুতরাং উত্তর দেওয়ার আগে কমান্ডটি শেষ না হওয়া পর্যন্ত অপেক্ষা করবে। কিছু কমান্ড কখনই শেষ হয় না (চেষ্টা করুন, উদাহরণস্বরূপ 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

লক্ষ্য। যদি আপনি মনে করেন যে আপনাকে কোনও কমান্ডটি একটি শূন্য ফাঁকা স্ট্রিং আউটপুট দেয় কিনা তা নির্ধারণ করতে হবে, আপনার খুব সম্ভবত একটি এক্সওয়াই সমস্যা আছে।


আমি মনে করি এই উত্তরটি বরং প্রশংসিত। আমি সমাধান কিছু এখানে 3 ইনপুট পরিস্থিতিতে প্রত্যেকের জন্য 100 পুনরাবৃত্তিও ব্যবহার কর্মক্ষমতা-পরীক্ষার হয়েছিল ( seq 1 10000000, seq 1 20, এবং printf"")। একমাত্র ম্যাচআপ যা এই পঠন পদ্ধতিটি জিতেনি তা ছিল -z "$(command)"খালি ইনপুটটির সাথে যোগাযোগ করা। তারপরেও এটি প্রায় 10-15% হারায়। তারা প্রায় কাছাকাছি বিরতি বলে মনে হচ্ছে seq 1 10। নির্বিশেষে, ইনপুট আকারটি বাড়ার সাথে সাথে -z "$(command)"পদ্ধতির এত ধীর হয়ে যায় যে আমি কোনও পরিবর্তনশীল-আকারের ইনপুটটির জন্য এটি ব্যবহার করা এড়াতে চাই।
আবাতুর

0

এখানে একটি বিকল্প পন্থা যা কিছু কমান্ডের 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"

0

কখনও কখনও আপনি আউটপুটটি সংরক্ষণ করতে চান, যদি এটি খালি না থাকে তবে এটি অন্য কমান্ডে প্রেরণ করতে পারেন। যদি তা হয় তবে আপনি এর মতো কিছু ব্যবহার করতে পারেন

list=`grep -l "MY_DESIRED_STRING" *.log `
if [ $? -eq 0 ]
then
    /bin/rm $list
fi

এইভাবে, rmতালিকাটি খালি থাকলে কমান্ডটি স্থগিত হবে না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.