আমি কীভাবে কেবল ডিরেক্টরিতে লুপ করব?


249

আমার কাছে কিছু ডিরেক্টরি এবং কিছু ফাইলের ফোল্ডার রয়েছে (কিছু লুকানো রয়েছে, বিন্দু দিয়ে শুরু হয়)।

for d in *; do
 echo $d
done

সমস্ত ফাইলের মধ্য দিয়ে লুপ হবে, তবে আমি কেবল ডিরেক্টরিগুলির মাধ্যমে লুপ করতে চাই। আমি কেমন করে ঐটি করি?

উত্তর:


331

আপনি কেবল ডিরেক্টরিগুলির সাথে মেলে শেষে স্ল্যাশ নির্দিষ্ট করতে পারেন:

for d in */ ; do
    echo "$d"
done

7
মনে রাখবেন যে এটিতে ডিরেক্টরিগুলির প্রতিলিঙ্কগুলিও অন্তর্ভুক্ত রয়েছে।
স্টাফেন চেজেলাস

1
তাহলে আপনি কীভাবে প্রতীকগুলি বাদ দেবেন?
rubo77

3
@ রুবো :77: [[ -L $d ]]$ d একটি প্রতীকী লিঙ্ক কিনা তা দিয়ে আপনি পরীক্ষা করতে পারেন ।
চোরোবা

1
@ অ্যাসেমল্যাবস এটি ভুল, set -Pকেবল নির্দেশগুলি পরিবর্তন করে যা ডিরেক্টরি পরিবর্তন করে। sprunge.us/TNac
ক্রিস ডাউন

4
@ চোরোবা: [[ -L "$f" ]]এই ক্ষেত্রে প্রতিলিঙ্কগুলি বাদ দেবে না , আপনাকে ট্রিলিং স্ল্যাশটি ছাঁটাই করতে হবে ( */পিছনের স্ল্যাশের সাথে লিঙ্কের জন্য পরীক্ষা[[ -L "${f%/}" ]] দেখুন )
রুবো

78

আপনি এটি দিয়ে পরীক্ষা করতে পারেন -d:

for f in *; do
    if [ -d "$f" ]; then
        # $f is a directory
    fi
done

এটি ফাইল টেস্ট অপারেটরগুলির মধ্যে একটি


8
দ্রষ্টব্য যে এটি ডিরেক্টরিতে প্রতিলিঙ্কগুলি অন্তর্ভুক্ত করবে।
স্টাফেন চেজেলাস

21
if [[ -d "$f" && ! -L "$f" ]]
প্রতীকগুলি

খালি ডিরেক্টরি ভাঙ্গবে। if [[ "$f" = "*" ]]; then continue; fi
পিসকভর

30

সতর্কতা অবলম্বন করুন যে চোরোবার সমাধানটি যদিও মার্জিত, তবুও যদি বর্তমান ডিরেক্টরিতে কোনও ডিরেক্টরি উপলব্ধ না হয় তবে অপ্রত্যাশিত আচরণ প্রকাশ করতে পারে। এই অবস্থায় forলুপটি এড়িয়ে যাওয়ার পরিবর্তে ব্যাশ লুপটি ঠিক একবার চালাবে যেখানে dসমান হবে */:

#!/usr/bin/env bash

for d in */; do
    # Will print */ if no directories are available
    echo $d
done

আমি এই কেস থেকে রক্ষা করতে নিম্নলিখিতটি ব্যবহার করার পরামর্শ দিচ্ছি:

#!/usr/bin/env bash

for f in *; do
    if [ -d ${f} ]; then
        # Will not run if no directories are available
        echo $f
    fi
done

এই কোডটি বর্তমান ডিরেক্টরিতে সমস্ত ফাইলের মধ্য দিয়ে লুপ হয়ে যাবে, ডিরেক্টরিটি কিনা fতা পরীক্ষা করে দেখুন , fযদি শর্তটি সত্য হয় তবে প্রতিধ্বনিত হয় । যদি fসমান */, echo $fচালানো হবে না।


3
অনেক সহজ shopt -s nullglob
চোরোবা

21

যদি আপনার কেবলমাত্র ডিরেক্টরি ব্যবহারের চেয়ে আরও নির্দিষ্ট ফাইল নির্বাচন করতে হয় findএবং এটিকে পাস করতে হবে while read:

shopt -s dotglob
find * -prune -type d | while IFS= read -r d; do 
    echo "$d"
done

shopt -u dotglobলুকানো ডিরেক্টরিগুলি (বা setopt dotglob/ unsetopt dotglobzsh এ) বাদ দিতে ব্যবহার করুন ।

IFS=এর মধ্যে একটিতে থাকা ফাইলের নামগুলি বিভক্ত করা এড়াতে $IFSউদাহরণস্বরূপ:'a b'

দেখতে AsymLabs উত্তর আরো জন্য নিচের findঅপশন


সম্পাদনা করুন:
আপনাকে যখন লুপের মধ্যে থেকে একটি প্রস্থান মান তৈরি করতে হবে, আপনি এই কৌশল দ্বারা অতিরিক্ত সাবশেলটি অবরুদ্ধ করতে পারেন:

while IFS= read -r d; do 
    if [ "$d" == "something" ]; then exit 1; fi
done < <(find * -prune -type d)

2
: আমি এই সমাধান পাওয়া stackoverflow.com/a/8489394/1069083
rubo77

11

আপনি এটির জন্য খাঁটি বাশ ব্যবহার করতে পারেন তবে এটি সন্ধান করা আরও ভাল:

find . -maxdepth 1 -type d -exec echo {} \;

(অতিরিক্তভাবে লুকানো ডিরেক্টরি অন্তর্ভুক্ত করা হবে সন্ধান করুন)


8
দ্রষ্টব্য যে এটি ডিরেক্টরিতে প্রতিলিঙ্কগুলি অন্তর্ভুক্ত করে না। লুকানো ডিরেক্টরি অন্তর্ভুক্ত করার shopt -s dotglobজন্য bashআপনি ব্যবহার করতে পারেন । আপনারও এতে অন্তর্ভুক্ত থাকবে .। এছাড়াও নোট করুন যে -maxdepthএকটি আদর্শ বিকল্প নয় ( -pruneহয়)।
স্টাফেন চেজেলাস

2
dotglobবিকল্প আকর্ষণীয় কিন্তু dotglobশুধুমাত্র ব্যবহার প্রযোজ্য *find .সর্বদা লুকানো ডিরেক্টরি অন্তর্ভুক্ত করা হবে (এবং বর্তমান দির পাশাপাশি)
রুও 77

6

রুট ডিরেক্টরিটি বাদ দিয়ে বর্তমান ওয়ার্কিং ডিরেক্টরিতে দৃশ্যমান এবং লুকানো উভয় ডিরেক্টরিই এটি অনুসন্ধান করার জন্য করা হয়:

ডিরেক্টরি মাধ্যমে লুপ করতে:

 find -path './*' -prune -type d

ফলাফল মধ্যে symlinks অন্তর্ভুক্ত:

find -L -path './*' -prune -type d

প্রতিটি ডিরেক্টরিতে কিছু করার জন্য (সিমলিঙ্কগুলি বাদে):

find -path './*' -prune -type d -print0 | xargs -0 <cmds>

লুকানো ডিরেক্টরিগুলি বাদ দিতে:

find -path './[^.]*' -prune -type d

প্রত্যাশিত মানগুলিতে একাধিক কমান্ড কার্যকর করতে (খুব স্বীকৃত উদাহরণ):

find -path './[^.]*' -prune -type d -print0 | xargs -0 -I '{}' sh -c \
"printf 'first: %-40s' '{}'; printf 'second: %s\n' '{}'"

'sh -c' এর পরিবর্তে 'বাশ-সি' ইত্যাদি ব্যবহার করতে পারেন


যদি প্রতি ইকো * / 'ইন' এর জন্য প্রতি ইকো * / 'থাকে তবে কি হবে 60,000 ডিরেক্টরি?
AsymLabs

আপনি "অনেকগুলি ফাইল" ত্রুটি পাবেন তবে এটি সমাধান করা যেতে পারে: ডেবিয়ানে "অনেক বেশি ফাইল খোলা" কীভাবে করবেন
রুও 77

1
Xargs উদাহরণ কেবল 9e.g. ডিরেক্টরি নামের সাবসেটের জন্য কাজ করবে would স্পেস বা নিউলাইনগুলিযুক্ত তারা কাজ করবে না)। ... -print0 | xargs -0 ...সঠিক নামগুলি কী কী তা আপনি যদি না জানেন তবে ব্যবহার করা ভাল ।
অ্যান্থন

1
@ রুবো 77 হ'ল লুকানো ফাইল / ডিরেক্টরি এবং একাধিক কমান্ড কার্যকর করার উপায় যুক্ত করেছে - অবশ্যই এটি কোনও স্ক্রিপ্টের সাহায্যেও করা যেতে পারে।
AsymLabs

1
আমি নীচে আমার উত্তরে একটি উদাহরণ যুক্ত করেছি, কীভাবে প্রতিটি ডিরেক্টরিতে কোনও ফাংশন ব্যবহার করে কিছু করা যায়find * | while read file; do ...
রুবো

3

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

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

দ্রষ্টব্য: তালিকাটি */ .*/ব্যাশে কাজ করে তবে ফোল্ডারগুলি প্রদর্শন করে .এবং ..zsh এ থাকায় এটি প্রদর্শন করবে না তবে ফোল্ডারে কোনও লুকানো ফাইল না থাকলে একটি ত্রুটি নিক্ষেপ করবে

একটি ক্লিনার সংস্করণ যা লুকানো ডিরেক্টরি অন্তর্ভুক্ত করবে এবং বাদ দেবে .. / ডটগ্লোব বিকল্পের সাথে থাকবে:

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

(বা setopt dotglobজেডএসে)

আপনি ডটগ্লোব আনসেট করতে পারেন

shopt -u dotglob

2

এটি তালিকায় প্রতিটি ডিরেক্টরিতে সম্পূর্ণ পাথ অন্তর্ভুক্ত করবে:

for i in $(find $PWD -maxdepth 1 -type d); do echo $i; done

1
স্পেস সহ ফোল্ডারগুলি ব্যবহার করার সময় বিরতি
আলেজান্দ্রো সাজো

0

ব্যবহার করুন findসঙ্গে -execডিরেক্টরি মাধ্যেমে লুপ করতে সময় ও কোনো কল ফাংশন Exec বিকল্প:

dosomething () {
  echo "doing something with $1"
}
export -f dosomething
find -path './*' -prune -type d -exec bash -c 'dosomething "$0"' {} \;

ব্যবহার করুন shopt -s dotglobঅথবা shopt -u dotglobঅন্তর্ভুক্ত করা / লুকানো ডিরেক্টরি অগ্রাহ্য


0

এটি প্রদত্ত পথে সাব-ডিরেক্টরি সংখ্যার সাথে সমস্ত ডিরেক্টরিকে তালিকাবদ্ধ করে:

for directory in */ ; do D=$(readlink -f "$directory") ; echo $D = $(find "$D" -mindepth 1 -type d | wc -l) ; done

-1
ls -d */ | while read d
do
        echo $d
done

This is one directory with spaces in the name- তবে একাধিক হিসাবে পার্স করা হয়।
পিসকভোর

-5
ls -l | grep ^d

বা:

ll | grep ^d

আপনি এটি একটি উপনাম হিসাবে সেট করতে পারেন


1
দুর্ভাগ্যক্রমে, আমি মনে করি না যে এটির প্রশ্নের উত্তর, যা ছিল "আমি কেবল ডিরেক্টরিগুলির মাধ্যমে লুপ করতে চাই" - যা এই lsভিত্তিক উত্তরের চেয়ে কিছুটা আলাদা , যা ডিরেক্টরিগুলি তালিকাভুক্ত করে
জেফ শ্যাচলার

1
আউটপুটটি পার্স করা কখনই ভাল ধারণা নয় ls: mywiki.wooledge.org/ পার্সিংএলস
কোডফোরস্টার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.