একটি নির্দিষ্ট এক্সটেনশন সহ সমস্ত ফাইলের মধ্য দিয়ে লুপ করুন


109
for i in $(ls);do
    if [ $i = '*.java' ];then
        echo "I do something with the file $i"
    fi
done

আমি বর্তমান ফোল্ডারে প্রতিটি ফাইল লুপ করতে চাই এবং এটি কোনও নির্দিষ্ট এক্সটেনশনের সাথে মেলে কিনা তা পরীক্ষা করতে চাই। উপরের কোডটি কাজ করে না, আপনি কেন জানেন?


4
কি হবে for i in $(ls *.java); do echo "do something with file $i"; done?
স্পিকার 15

বিবৃতি যদি তা ঠিক করার কোন উপায় নেই?
এআর 89

1
আপনি $iআক্ষরিক স্ট্রিং "*। জাভা" এর সাথে তুলনা করছেন; প্যাটার্ন সম্প্রসারণ এখানে করা হয় না।
চিপনার

যদি বিবৃতি আপনার কাছে যেমন থাকে তেমন ঠিক করতে, ব্যবহার করুন if [[ $i == *.java ]]; then.. (ডাবল [[]] গুলি এবং অব্যক্ত * জাভা নোট করুন)।
অন্য লোকটি

2
বিশ্লেষণ করবেন নাls - @ চিপনারের উত্তর গ্রহণ করুন
গ্লেন জ্যাকম্যান

উত্তর:


201

কোনও অভিনব ট্রিকস প্রয়োজন নেই:

for i in *.java; do
    [ -f "$i" ] || break
    ...
done

প্রহরীটি নিশ্চিত করে যে যদি কোনও মিলে যাওয়া ফাইল না থাকে তবে অস্তিত্বহীন ফাইলের নামটি প্রক্রিয়া না করে লুপটি প্রস্থান করবে *.java। ইন bash(অথবা শেল অনুরূপ কিছু সমর্থনকারী), আপনি ব্যবহার করতে পারেন nullglobবিকল্প কেবল একটি ব্যর্থ ম্যাচ উপেক্ষা করার এবং লুপ শরীরে প্রবেশ না।

shopt -s nullglob
for i in *.java; do
    ...
done

5
সহজ উপায় আরেকটি প্যাটার্ন যোগ করার জন্য হল: for i in *.java *.cpp; do। আপনি নিদর্শন সক্রিয় বাড়ানো তাহলে bashসঙ্গে shopt -s extglob, আপনি লিখতে পারেন for i in *.@(java|cpp); do
চ্যানার

8
এটি যদি আসলে কোনও ফাইলের সাথে মেলে will আপনাকে shopt -s nullglobএমনটি ব্যবহার করতে হবে যাতে কোনও মিল না-করা প্যাটার্নটি আক্ষরিকভাবে চিকিত্সার পরিবর্তে খালি অনুক্রমে প্রসারিত হয়।
চিপনার

1
@zygimantus হ্যাঁ এটি হওয়া উচিত, এতক্ষণ বর্তমান ডিরেক্টরি যেখানে স্ক্রিপ্টটি চালু আছে। আপনি যে ডিরেক্টরিটিতে থাকতে চান তা যদি না হন cdতবে forলুপটি শুরু করার আগে আপনার সেই ডিরেক্টরিটি করা উচিত
ড্যানিয়েলসডেস্ক

1
@puk এটি আপনার শেল বিকল্পগুলির উপর নির্ভর করে। ডিফল্টরূপে, একটি মিল না হওয়া প্যাটার্নটিকে আক্ষরিক স্ট্রিং হিসাবে বিবেচনা করা হয়। আপনি nullglobএটিকে একটি খালি অনুক্রম হিসাবে গণ্য করতে সেট করতে পারেন, বা failglobএটিকে একটি ত্রুটি হিসাবে বিবেচনা করার জন্য সেট করতে পারেন। (যদি আপনি উভয়টি সেট করেন তবে failglobঅগ্রাধিকার
নেন

3
@ চেপনার অ বিশেষজ্ঞদের পক্ষে উত্তরে এটি সূচিত হওয়া কার্যকর হতে পারে কারণ কেউ এটিকে অনুলিপি করে পেস্ট করতে পারে এবং এটি কাজ করছে না বলে মনে করতে পারে। একটি নিখুঁত উদাহরণ কেউ সমস্ত "রূপান্তরের উদ্দেশ্যে হবে " এ .jpg "ফাইল একটি অত্যন্ত গুরুত্বপূর্ণ ফাংশন পূরণকল্পে আগে .png"
PUK

13

সঠিক উত্তরটি হ'ল @ চিপনার্স

EXT=java
for i in *.${EXT}; do
    ...
done

তবে ফাইলনামের দেওয়া এক্সটেনশন রয়েছে কিনা তা যাচাই করার জন্য এখানে একটি ছোট কৌশল:

EXT=java
for i in *; do
    if [ "${i}" != "${i%.${EXT}}" ];then
        echo "I do something with the file $i"
    fi
done

extপরিবর্তে পরিবর্তে এটি কিভাবে হবে .java?
এআর 89

13

পুনরাবৃত্তভাবে সাবফোল্ডার যুক্ত করুন,

for i in `find . -name "*.java" -type f`; do
    echo "$i"
done

পরিবর্তে find . -name "*.java" -type f -exec echo \{\} \; আউটপুট এর misparsing এড়াতেfind
umläute

1
এবং যদি আপনি না করেন, অন্তত আপনার "$i"লুপের ভিতরে উদ্ধৃতি দেওয়া উচিত ।
ট্রিপলি

2
যদি কোনও ফাইলের নামে সাদা জায়গা থাকে তবে এটি কাজ করবে না।
কোডফোরস্টার

1
@ কোডফোরস্টার আমার ঠিক এই সমস্যাটি ছিল এবং আমি এই উত্তরটি থেকে পদ্ধতিটি ব্যবহার করে এটি ঠিক করেছি: Askubuntu.com/a/343753/551184
fsinisi90

7

: লুপ দিয়ে শেষ সমস্ত ফাইল মাধ্যমে .img, .bin, .txtপ্রত্যয়, এবং ফাইলের নাম মুদ্রণ:

for i in *.img *.bin *.txt;
do
  echo "$i"
done

বা পুনরাবৃত্ত পদ্ধতিতে (সমস্ত উপ-ডিরেক্টরিতে এটিও সন্ধান করুন):

for i in `find . -type f -name "*.img" -o -name "*.bin" -o -name "*.txt"`;
do
  echo "$i"
done

3

আমি ফাইলগুলির মধ্য দিয়ে লুপ দেওয়ার সঠিক উপায় সম্পর্কিত অন্যান্য উত্তরগুলি মেনে নেব। তবে ওপি জিজ্ঞাসা করেছে:

উপরের কোডটি কাজ করে না, আপনি কেন জানেন?

হ্যাঁ!

একটি দুর্দান্ত নিবন্ধ পরীক্ষার মধ্যে পার্থক্য কী, [এবং [[?]] বিস্তারিতভাবে ব্যাখ্যা করেছে যে অন্যান্য পার্থক্যের মধ্যেও আপনি কমান্ডের মধ্যে expression matchingবা ব্যবহার করতে পারবেন না (যা সংক্ষিপ্ততর )pattern matchingtest[

নতুন পরীক্ষা বৈশিষ্ট্যযুক্ত [[পুরানো পরীক্ষা [উদাহরণ

প্যাটার্ন মিল = (বা ==) (উপলভ্য নয়) [[$ নাম = ক *]] || প্রতিধ্বনি "নাম একটি 'ক': $ নাম" দিয়ে শুরু হয় না

নিয়মিত এক্সপ্রেশন = ~ (উপলভ্য নয়) [[$ (তারিখ) = ~ ri শুক্র \ ... \ 13]] && প্রতিধ্বনি "এটি 13 ই শুক্রবার!"
ম্যাচিং

সুতরাং আপনার স্ক্রিপ্ট ব্যর্থতার কারণ। যদি ওপি [[সিনট্যাক্সের সাথে কোনও উত্তর (( [কমান্ডের মতো যতগুলি প্ল্যাটফর্মে সমর্থিত না হওয়ার অসুবিধা রয়েছে ) নিয়ে আগ্রহী হয়, তবে আমি আমার উত্তরটি এতে যুক্ত করে সম্পাদনা করতে পেরে খুশি হব)

সম্পাদনা: উত্তরে ডেটা টেবিল হিসাবে ফর্ম্যাট করার জন্য যে কোনও প্রতিরক্ষা সহায়ক হবে!


2

যেমন @ চ্যাপনার তার মন্তব্যে বলেছেন আপনি $ i একটি নির্দিষ্ট স্ট্রিংয়ের সাথে তুলনা করছেন।

পরিস্থিতিটি প্রসারিত ও সংশোধন করতে আপনার [[]] রেজেক্স অপারেটরের সাথে = ~ ব্যবহার করা উচিত ~

উদাহরণ:

for i in $(ls);do
    if [[ $i =~ .*\.java$ ]];then
        echo "I want to do something with the file $i"
    fi
done

= of এর ডানদিকে রেজেক্সটি বাম হাতের অপারেটরের মানটির বিরুদ্ধে পরীক্ষা করা হয় এবং উদ্ধৃত করা উচিত নয়, (উদ্ধৃত ত্রুটি হবে না তবে একটি নির্দিষ্ট স্ট্রিংয়ের সাথে তুলনা করবে এবং সম্ভবত ব্যর্থ হবে "

তবে উপরের গ্লোব ব্যবহার করে @ চ্যাপনারের উত্তরটি অনেক বেশি কার্যকর প্রক্রিয়া।


extপরিবর্তে পরিবর্তে এটি কিভাবে হবে .java?
এআর 89

1
আক্ক, নিয়মিত প্রকাশের প্রয়োজন নেই: if [[ $i == *.java ]]বা if [[ $i == *.$ext ]]। তবে ls কে পার্স করবেন না
গ্লেন জ্যাকম্যান

1

আমি এই সমাধানটি বেশ সুবিধাজনক বলে খুঁজে পেয়েছি। এটি ব্যবহার করে-or বিকল্পটিfind :

find . -name \*.tex -or -name "*.png" -or -name "*.pdf"

এটা তোলে এক্সটেনশন ফাইল পাবেন tex, pngএবং pdf

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