লিনাক্সে ডিরেক্টরিগুলি কীভাবে লুপ করবেন?


168

আমি লিনাক্সে ব্যাশে একটি স্ক্রিপ্ট লিখছি এবং প্রদত্ত ডিরেক্টরিতে সমস্ত সাব ডিরেক্টরি ডিরেক্টরি লিখতে হবে। আমি কীভাবে এই ডিরেক্টরিগুলি লুপ করব (এবং নিয়মিত ফাইলগুলি এড়িয়ে যেতে পারি)?

উদাহরণস্বরূপ:
প্রদত্ত ডিরেক্টরিতে /tmp/
এটির নিম্নলিখিত উপ-ডিরেক্টরি রয়েছে:/tmp/A, /tmp/B, /tmp/C

আমি এ, বি, সি পুনরুদ্ধার করতে চাই


উত্তর:


129
cd /tmp
find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n'

একটি সংক্ষিপ্ত ব্যাখ্যা:

  • find ফাইলগুলি সন্ধান করে (বেশ স্পষ্টতই)

  • .বর্তমান ডিরেক্টরী পর যা cdহয় /tmp(এই প্রোগ্রামটিতে এই না থাকার চেয়ে বেশি নমনীয় /tmpসরাসরি findকমান্ড। আপনি শুধুমাত্র একটি স্থানে আছে, cd, পরিবর্তন জন্য, আপনাকে আরো ক্রিয়া এই ফোল্ডারে জায়গা নিতে চান)

  • -maxdepth 1এবং -mindepth 1নিশ্চিত করুন যে findকেবলমাত্র বর্তমান ডিরেক্টরিতে .দেখেছে এবং ফলাফলের মধ্যে নিজেকে অন্তর্ভুক্ত করবে না

  • -type d কেবল ডিরেক্টরিগুলির জন্য দেখায়

  • -printf '%f\n প্রতিটি হিটের জন্য কেবল পাওয়া ফোল্ডারের নাম (প্লাস একটি নতুন লাইন) মুদ্রণ করে।

এট ভয়েইল!


উপায় দ্বারা: দ্রষ্টব্য, যে সমস্ত উত্তরগুলি লুকানো ফোল্ডারগুলিও খুব সন্ধান করবে (এটি হ'ল ফোল্ডারগুলি একটি বিন্দু দিয়ে শুরু করবে)! আপনি যদি এটি না চান তবে প্রিন্টএফ বা এক্সিকিউটিভ বিকল্পগুলির আগে `-regex '\ ./ [^ \।]। *' Add যুক্ত করুন।
বোল্ডউইন

1
সহায়ক - আপনার যদি প্রতিটি হিটের জন্য কেবল একটি কমান্ড কার্যকর করতে হয় ;-) - কেবলমাত্র মৃত্যুদণ্ড কার্যকর করার জন্য আমার কাছে কয়েকটি কমান্ড রয়েছে :-(।
মার্টিন

কোনও সমস্যা নেই: এই সমাধানটি মানিয়ে নিন: transnum.blogspot.de/2008/11/…while..done লুপের ভিতরে আপনি পাগল হতে পারেন।
বোল্ডউইন

1
কিছু ব্যবহারের ক্ষেত্রে এটি খুব সুন্দর পদ্ধতি; findএর -execবিকল্পটি আপনাকে প্রতিটি ফাইল / ডিরেক্টরিতে কোনও কমান্ড চালাতে দেয়।
jtpereyda

451

এখন পর্যন্ত সমস্ত উত্তর ব্যবহার করা হয়েছে find, সুতরাং এখানে কেবল শেল দিয়ে একটি দেওয়া আছে। আপনার ক্ষেত্রে বাহ্যিক সরঞ্জামের প্রয়োজন নেই:

for dir in /tmp/*/     # list directories in the form "/tmp/dirname/"
do
    dir=${dir%*/}      # remove the trailing "/"
    echo ${dir##*/}    # print everything after the final "/"
done

18
+1 - findআপনি যখন ওয়াইল্ডকার্ডে স্ল্যাশ যুক্ত করতে পারেন তখন কেন বিরক্ত
হবেন

19
তাই for dir in */; do echo $dir; doneবর্তমান ডিরেক্টরির মধ্যে ডিরেক্টরি জন্য।
এহতেশ চৌধুরী

41
এটিতে কী করছে dir=${dir%*/}এবং echo ${dir##*/}কী করছে তার ব্যাখ্যা থাকতে পারে তা যদি ভালো হয়।
জেরেমি এস

11
এটি কারণ ভেরিয়েবল দির শেষে ব্যাকস্ল্যাশ অন্তর্ভুক্ত করবে। একটি পরিষ্কার নাম রাখতে তিনি এটিকে সরাচ্ছেন। % শেষে / অপসারণ করবে। ## শুরুতে / সরিয়ে দেবে। এগুলি সাবস্ট্রিংগুলি পরিচালনা করার জন্য অপারেটর।
sfratini

8
যদি কোনও মিল নেই, লুপটি ট্রিগার করা হবে /tmp/*/, ডিরেক্টরিটি আসলে বিদ্যমান কিনা তা পরীক্ষা করে দেখার জন্য এটি বুদ্ধিমানের কাজ হবে।
Jrs42

41

আপনি গোপন পরিচালক (সমস্ত বিন্দু দিয়ে শুরু করে) সহ সমস্ত ডিরেক্টরি লুপ করতে পারেন:

for file in */ .*/ ; do echo "$file is a directory"; done

দ্রষ্টব্য: ফোল্ডারে কমপক্ষে একটি গোপন ডিরেক্টরি উপস্থিত থাকলে তালিকাটি */ .*/zsh এ কাজ করে। ব্যাশে এটিও প্রদর্শিত হবে .এবং..


বাশার জন্য লুকানো ডিরেক্টরিগুলি অন্তর্ভুক্ত করার আর একটি সম্ভাবনা হ'ল:

shopt -s dotglob;
for file in */ ; do echo "$file is a directory"; done

আপনি যদি চিহ্নগুলি বাদ দিতে চান:

for file in */ ; do 
  if [[ -d "$file" && ! -L "$file" ]]; then
    echo "$file is a directory"; 
  fi; 
done

প্রতিটি সমাধানে কেবল অনুসরণযোগ্য ডিরেক্টরি নামের (এ, বি, সি) আউটপুট করতে লুপগুলির মধ্যে এটি ব্যবহার করুন:

file="${file%/}"     # strip trailing slash
file="${file##*/}"   # strip path and leading slash
echo "$file is the directoryname without slashes"

উদাহরণ (এটি এমন ডিরেক্টরিগুলির সাথেও কাজ করে যেখানে স্পেস রয়েছে):

mkdir /tmp/A /tmp/B /tmp/C "/tmp/ dir with spaces"
for file in /tmp/*/ ; do file="${file%/}"; echo "${file##*/}"; done

16

স্পেস রয়েছে এমন ডিরেক্টরিগুলির সাথে কাজ করে

সর্পিগাল দ্বারা অনুপ্রাণিত

while IFS= read -d $'\0' -r file ; do 
    echo $file; ls $file ; 
done < <(find /path/to/dir/ -mindepth 1 -maxdepth 1 -type d -print0)

আসল পোস্ট (স্পেস দিয়ে কাজ করে না)

বোল্ডউইন দ্বারা অনুপ্রাণিত : findকমান্ড সহ লুপের উদাহরণ ।

for D in $(find /path/to/dir/ -mindepth 1 -maxdepth 1 -type d) ; do
    echo $D ;
done

9
find . -mindepth 1 -maxdepth 1 -type d -printf "%P\n"

এটি খুব সুন্দর এবং প্রয়োজনীয়তাও দূর করে basename। আমি আমার উত্তরের চেয়ে এটিকে পছন্দ করব।
বোল্ডউইন

6

আমি প্রায়শই যে কৌশলটি ব্যবহার করি তা হ'ল find | xargs। উদাহরণস্বরূপ, আপনি যদি এই ডিরেক্টরিতে প্রতিটি ফাইল এবং এর সমস্ত উপ-ডিরেক্টরিকে বিশ্ব-পঠনযোগ্য করতে চান তবে আপনি এটি করতে পারেন:

find . -type f -print0 | xargs -0 chmod go+r
find . -type d -print0 | xargs -0 chmod go+rx

-print0বিকল্প একটি স্থান পরিবর্তে একটি শূন্য অক্ষর দিয়ে বন্ধ। দ্য-0বিকল্প তার ইনপুট একই ভাবে splits। সুতরাং এটি স্পেস সহ ফাইলগুলিতে ব্যবহারের সংমিশ্রণ।

আপনি প্রতিটি লাইন আউটপুট গ্রহণ করে findএবং এটির শেষে এটি স্টিক করে কমান্ডের এই চেইনটিকে চিত্রিত করতে পারেনchmod কমান্ডের ।

আপনি যদি আদেশটি শেষের পরিবর্তে মাঝখানে তার যুক্তি হিসাবে চালাতে চান তবে আপনাকে কিছুটা সৃজনশীল হতে হবে। উদাহরণস্বরূপ, আমার প্রতিটি উপ-ডিরেক্টরিতে পরিবর্তিত হয়ে কমান্ড চালানো দরকার latemk -c। সুতরাং আমি ( উইকিপিডিয়া থেকে ) ব্যবহার করেছি :

find . -type d -depth 1 -print0 | \
    xargs -0 sh -c 'for dir; do pushd "$dir" && latexmk -c && popd; done' fnord

এটির প্রভাব রয়েছে for dir $(subdirs); do stuff; doneতবে তাদের নামে ফাঁকা স্থানের ডিরেক্টরিতে নিরাপদ। এছাড়াও, পৃথক কলগুলি stuffএকই শেলটিতে করা হয়, এ কারণেই আমার কমান্ডে আমাদের সাথে বর্তমান ডিরেক্টরিতে ফিরে যেতে হবে popd


3

একটি ন্যূনতম বাশ লুপ আপনি তৈরি করতে পারেন (ঘোস্টডোগ answer৪ উত্তর ভিত্তিতে)

for dir in directory/*                                                     
do                                                                                 
  echo ${dir}                                                                  
done

ডিরেক্টরি দ্বারা ফাইল একটি গোছা জিপ করতে

for dir in directory/*
do
  zip -r ${dir##*/} ${dir}
done                                               

এটি directoryকেবলমাত্র সাব-ডাইরেক্টরিগুলিতে নয় সমস্ত ফাইলের তালিকা করে ।
ডেক্সটারিটাস


2

আপনি লুপের জন্য একটি একাধিক কমান্ড চালানো চান, আপনি ফল সংরক্ষণ করতে পারবেন findসঙ্গে mapfile(ব্যাশ> = 4) একটি পরিবর্তনশীল হিসাবে এবং অ্যারে দিয়ে যেতে ${dirlist[@]}। এটি ফাঁকা স্থান সম্বলিত ডিরেক্টরিগুলির সাথেও কাজ করে।

findকমান্ড উপর ভিত্তি করে তৈরি উত্তর Boldewyn দ্বারা। findকমান্ড সম্পর্কে আরও তথ্য সেখানে পাওয়া যাবে।

IFS=""
mapfile -t dirlist < <( find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n' )
for dir in ${dirlist[@]}; do
    echo ">${dir}<"
    # more commands can go here ...
done
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.