বাশ পুনরাবৃত্তি ফাইল তালিকা খালি ব্যতীত


33

আমি ভেবেছিলাম এটি সহজ হবে - তবে এটি আমার প্রত্যাশার চেয়ে জটিল প্রমাণিত হচ্ছে।

আমি একটি ডিরেক্টরিতে একটি নির্দিষ্ট ধরণের সমস্ত ফাইলের মাধ্যমে পুনরাবৃত্তি করতে চাই, তাই আমি এটি লিখি:

#!/bin/bash

for fname in *.zip ; do
   echo current file is ${fname}
done

ডিরেক্টরিটিতে কমপক্ষে একটি ম্যাচিং ফাইল থাকা পর্যন্ত এটি কাজ করে। তবে যদি কোনও মেলানো ফাইল না থাকে তবে আমি এটি পাই:

current file is *.zip

আমি তখন চেষ্টা করেছি:

#!/bin/bash

FILES=`ls *.zip`
for fname in "${FILES}" ; do
    echo current file is ${fname}
done

যখন কোনও ফাইল নেই তখন লুপের বডি চালিত হয় না, আমি ls থেকে একটি ত্রুটি পেয়েছি:

ls: *.zip: No such file or directory

আমি কীভাবে কোনও লুপ লিখব যা পরিষ্কারভাবে কোনও মিল নেই ফাইলগুলি পরিচালনা করে?


7
shopt -s nullglobলুপ চালানোর আগে যুক্ত করুন ।
cuonglm

@ কুওলংলম: স্পষ্টতই ফলস্বরূপ ফলস্বরূপ এই আরএইচইল 5 বাক্সে খালি তালিকার পরিবর্তে এক্সিকিউটিভ স্ক্রিপ্টটির নাম ফিরে আসবে (ব্যাশ ৩.২.২৫) যদি আমি FILES=ls * .zip করি ; for fname in "${FILES}"...তবে এটি প্রত্যাশার মতো কাজ করেfor fname in *.zip ; do....
সিমকিয়ান

3
ব্যবহার for file in *.zip, না `ls ...`। @ কিউংলমের পরামর্শটি হ'ল *.zipপ্যাটার্নটি কোনও ফাইলের সাথে মেলে না nothing lsযুক্তি ছাড়াই বর্তমান ডিরেক্টরি তালিকা করে।
স্টাফেন চেজেলাস

1
এই প্রশ্নটি আলোচনা করে যে কেন lsসাধারণত আউটপুট পার্স করা যায়: পার্স করা হয় না কেন ? ls; বাশগুইডের পার্সিংএলস নিবন্ধের সেই পৃষ্ঠার শীর্ষের লিঙ্কটিও দেখুন
প্রধানমন্ত্রী 2 রিং

উত্তর:


34

ইন bash, আপনি nullglobবিকল্পটি সেট করতে পারেন যাতে একটি প্যাটার্ন যা আক্ষরিক স্ট্রিং হিসাবে বিবেচনা না করে "অদৃশ্য হয়ে যায়" কিছুই এর সাথে মেলে না:

shopt -s nullglob
for fname in *.zip ; do
   echo "current file is ${fname}"
done

পসিক্স শেল স্ক্রিপ্টে, আপনি কেবল যাচাই করে fnameফেলেছেন (এবং একই সাথে [ -f ]এটি পরীক্ষা করুন যে এটি একটি নিয়মিত ফাইল (বা নিয়মিত ফাইলের জন্য সিএমলিংক) এবং ডিরেক্টরি / ফিফো / ডিভাইসের মতো অন্য ধরণের নয় ...):

for fname in *.zip; do
    [ -f "$fname" ] || continue
    printf '%s\n' "current file is $fname"
done

যদি আপনি সমস্ত (গোপনীয় নয়) ফাইলগুলি লুপ করতে চান তবে এর নাম নির্বিশেষে যার নাম শেষ হয় তা [ -f "$fname" ]দিয়ে প্রতিস্থাপন করুন ।[ -e "$fname" ] || [ -L "$fname ].zip

প্রতিস্থাপন *.zipসঙ্গে .*.zip .zip *.zipকরেন তাহলে আপনি গোপন ফাইল যার নাম প্রান্ত মধ্যে বিবেচনা করতে .zip


1
shopt -s nullglobউবুন্টু 17.04-এ আমার পক্ষে কাজ করে নি, তবে [ -f "$fname" ] || continueভালভাবে কাজ করেছে।
কোপ্পোর

@ কোপ্পোর দেখে মনে হচ্ছে আপনি আসলে ব্যবহার করছেন না bash
চিপনার

2
set ./*                               #set the arg array to glob results
${2+":"} [ -e "$1" ] &&               #if more than one result skip the stat "$1"
printf "current file is %s\n" "$@"    #print the whole array at once

###or###

${2+":"} [ -e "$1" ] &&               #same kind of test
for    fname                          #iterate singly on $fname var for array
do     printf "file is %s\n" "$fname" #print each $fname for each iteration
done                                  

এখানে একটি মন্তব্যে আপনি একটি ফাংশন চাওয়া উল্লেখ করেছেন ...

file_fn()
    if     [ -e "$1" ] ||               #check if first argument exists
           [ -L "$1" ]                  #or else if it is at least a broken link
    then   for  f                       #if so iterate on "$f"
           do : something w/ "$f"
           done
    else   command <"${1-/dev/null}"    #only fail w/ error if at least one arg
    fi

 file_fn *

2

ব্যবহার করুন

export -f myshellfunc
find . -mindepth 1 -maxdepth 1 -type f -name '*.zip' -exec bash -c 'myshellfunc "$0"' {} \;

এটি কাজ করার export -fজন্য আপনার শেল ফাংশনটি রফতানি করতে হবে । এখন কার্যকর findকরে bashযা আপনার শেল ফাংশনটি কার্যকর করে এবং কেবল বর্তমান দির স্তরে রয়েছে।


যা উপ-ডিরেক্টরিগুলির মাধ্যমে পুনরাবৃত্তি করে এবং আমি ম্যাচগুলির জন্য বাশ ফাংশন (স্ক্রিপ্ট নয়) শুরু করতে চাই।
15-15 টা

@ সাইমসিবিয়ান আমি একক দির সীমাবদ্ধ করতে বাশ ফাংশন পরিচালনা করতে সম্পাদনা করেছি
দানি_ল

-3

পরিবর্তে:

FILES=`ls *.zip`

চেষ্টা করুন:

FILES=`ls * | grep *.zip`

এইভাবে যদি ls ব্যর্থ হয় (যা এটি আপনার ক্ষেত্রে হয়) এটি ব্যর্থ আউটপুট গ্রেপ করে এবং খালি ভেরিয়েবল হিসাবে ফিরে আসবে।

current file is      <---Blank Here

এটি "কোনও ফাইল খুঁজে পাওয়া যায় নি" ফিরিয়ে আনতে আপনি এটিতে কিছু যুক্তি যুক্ত করতে পারেন

#!/bin/bash

FILES=`ls * | grep *.zip`
if [[ $? == "0" ]]; then
    for fname in "$FILES" ; do
        echo current file is $fname
    done
else
    echo "No Files Found"
fi

এইভাবে যদি পূর্ববর্তী কমান্ডটি সফল হয় (0 মানের সাথে প্রস্থানিত) তবে এটি বর্তমান ফাইলটি মুদ্রণ করবে, অন্যথায় এটি "ফাইল খুঁজে পাওয়া যায় না" মুদ্রণ করবে


1
আমার মনে হয় এটা একটি খারাপ ধারণা আরও একটি প্রক্রিয়া (যোগ হয় grepবরং একটি ভাল সরঞ্জাম (ব্যবহার করে সমস্যা সমাধানের জন্য চেষ্টা করার চেয়ে) find) বা (বর্তমান সমাধান জন্য প্রাসঙ্গিক সেটিং পরিবর্তন shopt -s nullglob)
থমাস Baruchel

1
ওপির মন্তব্য অনুযায়ী তাদের মূল পোস্টে shopt -s nullglobকাজ করে না। আমি findআমার উত্তর যাচাই করার সময় চেষ্টা করেছি এবং এটি ব্যর্থ হতে থাকে। আমার মনে হয় রফতানি জিনিসটির কারণে দানি বলেছিলেন।
কিপ কে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.