স্ক্রিপ্টটি কার্যকর করার জন্য যদি কোনও প্যাটার্নের সাথে মিল রয়েছে এমন ফাইলগুলি পরীক্ষা করুন


29

আমি ifনির্দিষ্ট প্যাটার্নের সাথে মেলে এমন কোনও ফাইল আছে কিনা তা পরীক্ষা করার জন্য একটি বিবৃতি লেখার চেষ্টা করছি । ডিরেক্টরিতে যদি কোনও পাঠ্য ফাইল থাকে তবে এটি প্রদত্ত স্ক্রিপ্টটি চালানো উচিত।

আমার কোড বর্তমানে:

if [ -f /*.txt ]; then ./script fi

দয়া করে কিছু ধারণা দিন; আমি কেবলমাত্র .txtডিরেক্টরিতে স্ক্রিপ্টটি চালাতে চাই ।


3
আপনি কি "ডিরেক্টরি" থাকার কথা নিশ্চিত /? এছাড়াও, আপনি এর আগে একটি সেমিকোলন অনুপস্থিত fi
depquid

আমি সবচেয়ে পরিষ্কার শক্ত সমাধানটির মুখোমুখি হয়েছি হ'ল স্ট্যাকওভারফ্লোতে এখানে বর্ণিতfind হিসাবে ব্যবহার করা ।
জোশুয়া গোল্ডবার্গ

উত্তর:


39
[ -f /*.txt ]

যদি কেবলমাত্র একটি (এবং কেবলমাত্র একটি) অ গোপন ফাইল রয়েছে /যার নাম শেষ হয় .txtএবং যদি সেই ফাইলটি একটি নিয়মিত ফাইল বা একটি নিয়মিত ফাইলের একটি সিমলিংক হয় তবেই সত্যটি ফিরে আসবে ।

এর কারণ হ'ল ওয়াইল্ডকার্ডগুলি কমান্ডটি (এখানে [) দেওয়ার আগে শেল দ্বারা প্রসারিত হয় ।

যদি একটি সুতরাং /a.txtএবং /b.txt, [5 আর্গুমেন্ট পাস হবে: [, -f, /a.txt, /b.txtএবং ][তাহলে অভিযোগ করবে যে -fঅনেক আর্গুমেন্ট দেওয়া হয়েছে।

আপনি যদি পরীক্ষা করতে চান যে *.txtপ্যাটার্নটি কমপক্ষে একটি অ-গোপন ফাইলগুলিতে প্রসারিত হয় (নিয়মিত বা না):

shopt -s nullglob
set -- *.txt
if [ "$#" -gt 0 ]; then
  ./script "$@" # call script with that list of files.
fi
# Or with bash arrays so you can keep the arguments:
files=( *.txt )
# apply C-style boolean on member count
(( ${#files[@]} )) && ./script "${files[@]}"

shopt -s nullglobহয় bashনির্দিষ্ট, কিন্তু শাঁস পছন্দ ksh93, zsh, yash, tcshসমতুল্য বিবৃতি আছে।

মনে রাখবেন ডিরেক্টরির বিষয়বস্তু পড়ার মাধ্যমে ঐ ফাইল খুঁজে বের করে, এটা চেষ্টা করুন এবং সব যা সমাধান চেয়ে এটি আরো কার্যকরী করে তোলে এ ঐ ফাইল অ্যাক্সেস নয় যে মত কল কমান্ড lsবা statশেল দ্বারা নির্ণিত ফাইলের যে তালিকায়।

মান shসমতুল্য হবে:

set -- [*].txt *.txt
case "$1$2" in
  ('[*].txt*.txt') ;;
  (*) shift; script "$@"
esac

সমস্যাটি হল বোর্ন বা পসিক্স শেলগুলির সাথে, যদি কোনও প্যাটার্ন মেলে না তবে এটি নিজের কাছে প্রসারিত। সুতরাং যদি *.txtপ্রসারিত হয় *.txt, আপনি জানেন না এটি কারণ .txtএটি ডিরেক্টরিতে কোনও ফাইল নেই বা কারণ সেখানে একটি ফাইল রয়েছে *.txt। ব্যবহার [*].txt *.txtকরে উভয়ের মধ্যে বৈষম্য তৈরি করতে দেয়।


[ -f /*.txt ]তুলনায় বেশ দ্রুত compgen
ড্যানিয়েল বুহমার

@ ড্যানিয়েলবিহ্মার [ -f /*.txt ]ভুল হবে, তবে আমার ডিরেক্টরিতে এমন একটি ডিরেক্টরিতে যে 3425ফাইল রয়েছে 94সেগুলির মধ্যে ফাইলগুলি নন গোপন টেক্সট ফাইলগুলি compgen -G "*.txt" > /dev/null 2>&1হিসাবে দ্রুত উপস্থিত হবে set -- *.txt; [ "$#" -gt 0 ](আমার ক্ষেত্রে 10000 বার পুনরাবৃত্তি করার সময় উভয়ের জন্য 20.5 সেকেন্ড)।
স্টাফেন চেজেলাস

11

আপনি সর্বদা ব্যবহার করতে পারেন find:

find . -maxdepth 1 -type f -name "*.txt" 2>/dev/null | grep -q . && ./script

ব্যাখ্যা:

  • find . : বর্তমান ডিরেক্টরি অনুসন্ধান করুন
  • -maxdepth 1: উপ-ডিরেক্টরি অনুসন্ধান করবেন না
  • -type f : কেবল নিয়মিত ফাইল অনুসন্ধান করুন
  • name "*.txt" : শেষ হওয়া ফাইলগুলির জন্য অনুসন্ধান করুন .txt
  • 2>/dev/null : ত্রুটি বার্তাগুলিতে পুনঃনির্দেশ করুন /dev/null
  • | grep -q . : যে কোনও চরিত্রের জন্য গ্রেপ, কোনও অক্ষর না পাওয়া গেলে মিথ্যা ফিরিয়ে দেবে।
  • && ./script: ./scriptপূর্ববর্তী কমান্ডটি সফল হলে কেবল কার্যকর করুন ( &&)

2
findকেবল ফাইলগুলি অনুসন্ধান করতে সমস্যা হলেই এটি মিথ্যা প্রত্যাবর্তন করে, এটি কোনও ফাইল খুঁজে না পাওয়া সত্ত্বেও নয়। আউটপুটটি grep -q .কিছু খুঁজে পেয়েছে কিনা তা পরীক্ষা করতে আপনি পাইপ করতে চান ।
স্টাফেন চেজেলাস

@ স্টাফেন চ্যাজেলাস আপনি অবশ্যই একদম ঠিক আছেন। যদিও অদ্ভুত, আমি এটি পরীক্ষা করেছি এবং এটি কাজ করে বলে মনে হয়েছিল। অদ্ভুত কিছু অবশ্যই করা উচিত কারণ এটি আর হয় না। "ফাইলগুলি খুঁজতে সমস্যা আছে" কখন পাবেন?
টেরডন

@ ইটারডন, যখন কোনও ডিরেক্টরি অ্যাক্সেসযোগ্য থাকে বা আই / ও ত্রুটি বা কোনও সিস্টেমের দ্বারা ফিরে আসা কোনও ত্রুটি এটি কল করে। সেক্ষেত্রে পরে চেষ্টা করুন chmod a-x .
স্টাফেন চেজেলাস

8

একটি সম্ভাব্য সমাধান হ'ল বাশ অন্তর্নির্মিত compgen। এই কমান্ডটি গ্লোব্বিং প্যাটার্নের জন্য সমস্ত সম্ভাব্য ম্যাচ ফেরত দেয় এবং একটি প্রস্থান কোড রয়েছে যা ইঙ্গিত করে যে কোনও ফাইল মিলেছে কিনা।

compgen -G "/*.text" > /dev/null && ./script

যদিও দ্রুততর সমাধানগুলি খুঁজতে গিয়ে আমি এই প্রশ্নটি পেয়েছি।


1
গুড ফাইন্ড! আপনি যদি কোনও মাল্টি-বাইট লোকালে থাকেন তবে আপনি এটির সাথে কিছুটা উন্নতি করতে পারেন LC_ALL=C compgen -G "*.txt" > /dev/null
স্টাফেন চেজেলাস

7

এটি করার জন্য এখানে একটি লাইন রয়েছে:

$ ls
file1.pl  file2.pl

ফাইল বিদ্যমান

$ stat -t *.pl >/dev/null 2>&1 && echo "file exists" || echo "file doesn't exist"
file exists

ফাইল বিদ্যমান নেই

$ stat -t -- *.txt >/dev/null 2>&1 && echo "file exists" || echo "file don't exist"
file don't exist

এই পদ্ধতির ব্যবহার করে ||এবং &&ব্যাশ মধ্যে অপারেটর। এগুলি হ'ল "বা" এবং "এবং" অপারেটর।

সুতরাং যদি স্টেট কমান্ড $?0 এর সমান ফিরে আসে তবে প্রথমটিকে echoবলা হয়, যদি এটি 1 প্রদান করে, তবে দ্বিতীয়টি echoবলা হয়।

স্ট্যাট থেকে ফলাফল ফেরত

# a failure
$ stat -t -- *.txt >/dev/null 2>&1
$ echo "$?"
1

# a success
$ stat -t -- *.pl >/dev/null 2>&1
$ echo "$?"
0

এই প্রশ্নটি স্ট্যাকওভারফ্লোতে ব্যাপকভাবে কভার করা হয়েছে:


1
statযখন ls -dএকই কাজ করতে পারে তখন কেন নন স্ট্যান্ডার্ড ব্যবহার করবেন?
স্টাফেন চেজেলাস

আমি ভেবেছিলাম ls -dএকটি ডিরেক্টরি তালিকা? আমি যখন ls -d *.plউদাহরণস্বরূপ কেবলমাত্র ফাইলগুলির সাথে একটি ডিরেক্টরি তালিকা তৈরি করার চেষ্টা করেছি তখন কাজ করার কথা মনে হয় নি ।
slm

আপনি বাঁদিকে বিবৃতি প্রতিস্থাপন করতে পারেন &&দ্বারা ls *.txtএবং এটি পাশাপাশি কাজ করবে। নিশ্চিত করুন যে আপনি stdout এবং stderr /dev/null@slm এর পরামর্শ অনুসারে প্রেরণ করেছেন।
আনটনাট

1
আপনি ব্যবহার করেন তাহলে ls *.txtকোন ফাইল ডিরেক্টরি মধ্যে উপস্থিত আছে এই একটি ফিরে আসবে $? = 2, যা যদি এখনও সঙ্গে কাজ তারপর হবে, কিন্তু এই চয়নের জন্য আমার অন্যতম কারণ ছিল statবেশি ls। আমি সাফল্যের জন্য 0 এবং ব্যর্থতার জন্য 1 চাইছিলাম।
slm

ls -dতাদের সামগ্রীর পরিবর্তে ডিরেক্টরি তালিকাভুক্ত করা হয়। তাই ls -dশুধু করে lstatফাইলে, ঠিক গনুহ statআছে। শূন্য-বহির্গমন স্থিতি কমান্ড কী ব্যর্থতায় ফিরে আসে তা সিস্টেম নির্দিষ্ট, এটি তাদের উপর অনুমান করা সামান্যই বোধগম্য।
স্টাফেন চেজেলাস

4

চেজেলাস যেমন উল্লেখ করেছে, ওয়াইল্ডকার্ড সম্প্রসারণ একাধিক ফাইলের সাথে মিলে গেলে আপনার স্ক্রিপ্টটি ব্যর্থ হবে।

তবে, আমার কাছে একটি কৌশল আছে যা আমি ব্যবহার করতে পারি ( এমনকি এটি আমার খুব বেশি পছন্দ হয় না ):

PATTERN=(/*.txt)
if [ -f ${PATTERN[0]} ]; then
...
fi

কিভাবে এটা কাজ করে?

ওয়াইল্ডকার্ড সম্প্রসারণ ফাইলের একটি অ্যারের সাথে মিলবে, আমরা কিছু পেয়ে থাকলে প্রথমটি পাই, অন্যথায় কোনও মিল না থাকলে শূন্য।


আইএমও এটি এখানে সবচেয়ে কম খারাপ উত্তর। এগুলি সবাই দেখতে বেশ ভয়ঙ্কর বলে মনে হচ্ছে, যদিও ভাষা থেকে একটি প্রাথমিক বৈশিষ্ট্য অনুপস্থিত।
প্লাগওয়াশ

প্লাগওয়াশ এটি ইচ্ছাকৃত ... যদি বাশ সফল হয় ... কারণ আপনি এটি থেকে যে আদেশগুলি ব্যবহার করেন তা স্তন্যপান করে
cb88

2
এটি ভুল যুক্তি (এবং আপনি উদ্ধৃতি অনুপস্থিত)। এটি প্রথম পরীক্ষামূলক ফাইলটি নিয়মিত ফাইল কিনা তা পরীক্ষা করে। এটি একটি নিয়মিত নিয়মিত ফাইল হতে পারে তবে নিয়মিত.txt টাইপের বেশ কয়েকটি ফাইল থাকতে পারে । উদাহরণস্বরূপ চেষ্টা করুন । mkdir a.txt; mkfifo b.txt; echo regular > c.txt
স্টাফেন চেজেলাস

1

সাধারণ হিসাবে:

cnt=`ls \*.txt 2>/dev/null | wc -l`
if [ "$cnt" != "0" ]; then ./script fi

wc -l প্রসারিত ওয়াইল্ডকার্ডে লাইন গণনা করে।


1
ডাউনভোট: এটি অল্প সংখ্যক কোডে আশ্চর্যজনক সংখ্যক শুরুর অ্যান্টিপ্যাটার্নগুলি সংগ্রহ করে। আপনার lsআউটপুটকে বিশ্লেষণ করা উচিত নয় এবং প্রায়শই $?সরাসরি পরীক্ষা করা উচিত নয় কারণ ifইতিমধ্যে তা। এছাড়াও, কিছু ঘটেছিল কিনা তা ব্যবহার wcকরে একইভাবে ভুল নির্দেশনা দেওয়া হয়েছে।
ট্রিপলি

0

আমি পূর্ববর্তী অ্যারে সমাধানটি পছন্দ করি তবে এটি প্রচুর সংখ্যক ফাইলের সাথে অপচয় হতে পারে - শেলটি অ্যারে তৈরি করতে মেমরির একটি দুর্দান্ত ব্যবহার করবে এবং কেবল প্রথম উপাদানটিই কখনও পরীক্ষা করা হবে।

এখানে গতকাল আমি একটি বিকল্প কাঠামো পরীক্ষা করেছি:

$ cd /etc; if [[ $(echo * | grep passwd) ]];then echo yes;else echo no;fi yes $ cd /etc; if [[ $(echo * | grep password) ]];then echo yes;else echo no;fi no

গ্রেপ থেকে প্রস্থান করার মান নিয়ন্ত্রণ কাঠামোর মাধ্যমে পথ নির্ধারণ করে বলে মনে হচ্ছে। এটি শেল নিদর্শনগুলির চেয়ে নিয়মিত প্রকাশের সাথেও পরীক্ষা করে। আমার কয়েকটি সিস্টেমে "পিসিগ্রেপ" কমান্ড রয়েছে যা আরও বেশি পরিশীলিত রেজেক্স ম্যাচের অনুমতি দেয়।

(উপরের সমালোচনাটি বিশ্লেষণের জন্য পড়ার পরে কমান্ড প্রতিস্থাপনের একটি "ls" মুছে ফেলার জন্য আমি এই উত্তরটি সম্পাদনা করেছি))


-2

যদি আপনি যদি একটি ধারা ব্যবহার করতে চান তবে গণনাটি মূল্যায়ন করুন:

if (( `ls *.txt 2> /dev/null|wc -l` ));then...
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.