লিনাক্স কমান্ড: কেবলমাত্র টেক্সট ফাইলগুলি কীভাবে 'অনুসন্ধান' করা যায়?


100

গুগল থেকে কয়েকটি অনুসন্ধানের পরে, আমি যা নিয়ে আসছি তা হ'ল:

find my_folder -type f -exec grep -l "needle text" {} \; -exec file {} \; | grep text

যা খুব অহেতুক এবং মাইম টাইপের তথ্যের মতো অপ্রয়োজনীয় পাঠ্যকে আউটপুট করে। এর থেকে আরও ভাল সমাধান? আমার কাছে একই ফোল্ডারে প্রচুর ছবি এবং অন্যান্য বাইনারি ফাইল রয়েছে যা আমাকে অনুসন্ধান করতে হবে।

উত্তর:


184

আমি জানি এটি একটি পুরানো থ্রেড, তবে আমি এটির পিছনে হোঁচট খেয়েছি এবং ভেবেছিলাম যে আমি আমার পদ্ধতিটি শেয়ার করব যা আমি findকেবলমাত্র বাইনারি ফাইলগুলি খুঁজে পাওয়ার জন্য খুব দ্রুত উপায় হিসাবে ব্যবহার করেছি :

find . -type f -exec grep -Iq . {} \; -print

-I, Grep করার বিকল্প বলে তা অবিলম্বে বাইনারি ফাইল ও উপেক্ষা করার .পাশাপাশি বিকল্প -qতা অবিলম্বে করতে হবে পাঠ্য ফাইল মেলে তাই এটি খুব দ্রুত চলে যায়। আপনি পরিবর্তন করতে পারেন -printএকটি থেকে -print0একটি মধ্যে বংশীধ্বনিতুল্য জন্য xargs -0আপনি শূণ্যস্থান সম্পর্কে উদ্বিগ্ন বা কিছু (টিপ জন্য ধন্যবাদ, @ lucas.werkmeister!)

এছাড়াও প্রথম বিন্দুটি শুধুমাত্র findওএস এক্স- এর মতো কয়েকটি বিএসডি সংস্করণগুলির জন্য প্রয়োজনীয় , তবে আপনি যদি এটি কোনও নাম বা কোনও কিছুতে রাখতে চান তবে এটি সর্বদা সেখানে থাকা কোনও কিছুতেই ক্ষতি করে না।

সম্পাদনা : @ আরসলান সঠিকভাবে উল্লেখ করেছেন -andযেহেতু এটি বোঝানো হয়েছে তাই বাদ দেওয়া যেতে পারে।


16
ম্যাক ওএস এক্সে আমার এটিকে পরিবর্তন করতে হবে find . -type f -exec grep -Il "" {} \;
অ্যালেক জ্যাকবসন

4
এটি পিরোর জবাবের চেয়ে ভাল কারণ ১. এটি আসলে প্রশ্নের উত্তর দেয় ২. এটি মিথ্যা ধনাত্মক ফল দেয় না 3.. এটি আরও পারফরম্যান্ট
ব্যবহারকারী 123444555621

4
আপনি find -type f -exec grep -Iq . {} \; -and -printযে ফাইলগুলির মধ্যে রাখেন সে সুবিধাটিও ব্যবহার করতে পারেন find; আপনি কেবলমাত্র পাঠ্য ফাইলের জন্য চালিত এমন -printঅন্যটির সাথে বিকল্প স্থাপন করতে পারেন -exec। (আপনি যদি grepফাইলের নাম মুদ্রণ করতে দেন তবে আপনি ফাইলের নামগুলিতে নতুন লাইনের সাথে আলাদা করতে সক্ষম হবেন না))
লুকাস ওয়ার্কমিস্টার

4
@ নাথানস.ওয়াটসন-হাই এটি হওয়া উচিত নয়, কারণ এটি অবিলম্বে পাঠ্য ফাইলগুলির সাথে মিল থাকা উচিত। আপনি ভাগ করতে পারেন একটি নির্দিষ্ট ব্যবহারের কেস আছে?
crudcore

4
find . -type f -exec grep -Il . {} +অনেক দ্রুত। -execত্রুটিটি হ'ল @ lucas.werkmeister এর পরামর্শ অনুযায়ী এটি আর বাড়ানো যায় না
হেনিং


10

অহঙ্কারী কেন? আপনার যদি এটি প্রায়শই ব্যবহার করার প্রয়োজন হয় এবং প্রতিবার এটি টাইপ করতে না চান তবে কেবল এটির জন্য একটি ব্যাশ ফাংশনটি সংজ্ঞায়িত করুন:

function findTextInAsciiFiles {
    # usage: findTextInAsciiFiles DIRECTORY NEEDLE_TEXT
    find "$1" -type f -exec grep -l "$2" {} \; -exec file {} \; | grep text
}

এটি আপনার মধ্যে রাখুন .bashrcএবং তারপর চালান:

findTextInAsciiFiles your_folder "needle text"

তুমি যখন চাও.


ওপি'র সম্পাদনা প্রতিফলিত করতে সম্পাদনা:

আপনি যদি মাইম তথ্যগুলি কাটাতে চান তবে আপনি কেবল পাইপলাইনে আরও একটি পর্যায় যুক্ত করতে পারেন যা মাইম তথ্যগুলি ফিল্টার করে। এই কৌতুক করতে হবে শুধুমাত্র গ্রহণ আগে কি আসে দ্বারা :: cut -d':' -f1:

function findTextInAsciiFiles {
    # usage: findTextInAsciiFiles DIRECTORY NEEDLE_TEXT
    find "$1" -type f -exec grep -l "$2" {} \; -exec file {} \; | grep text | cut -d ':' -f1
}

আমি নিশ্চিত নই যে "গ্রেপ টেক্সট" ঠিক সমস্ত পাঠ্য ফাইল পাওয়ার জন্য যথাযথ কিনা - আমার অর্থ, এমন কোনও পাঠ্য ফাইলের মাইম প্রকারের বর্ণনার স্ট্রিংয়ে কোনও 'পাঠ্য' নেই?
datasn.io

@ কাভির ডটকম: হ্যাঁ fileম্যানুয়াল থেকে : "ব্যবহারকারীরা ডিরেক্টরিতে সমস্ত পাঠযোগ্য ফাইল 'টেক্সট' শব্দটি মুদ্রিত আছে তা জানার উপর নির্ভর করে"
পেরো

4
গ্রেপিংয়ের আগে টেক্সট ফাইলগুলি অনুসন্ধান করার পরে গ্রিপিংয়ের পরিবর্তে এবং পাঠ্য ফাইলগুলি ছাঁটাই করা কি আরও চতুর হবে না?
ব্যবহারকারী অজানা

/proc/meminfo, /proc/cpuinfoইত্যাদি হ'ল পাঠ্য ফাইল, তবে file /proc/meminfoবলে /proc/meminfo: empty। আমি ভাবছি যে 'পাঠ্য' ছাড়াও 'ফাঁকা' পরীক্ষা করা উচিত কিনা, তবে নিশ্চিত নয় যে অন্য ধরণের ক্ষেত্রেও 'খালি' প্রতিবেদন করা যায় কিনা।
টিমো কাহকেনেন

"কেন অহঙ্কারী?" - "অনিবদ্ধ পাঠ্যকে আউটপুট দেয়"। এই উত্তর যে বপন না।
ব্যবহারকারী 123444555621

4
find . -type f -print0 | xargs -0 file | grep -P text | cut -d: -f1 | xargs grep -Pil "search"

এটি দুর্ভাগ্যক্রমে স্থান সংরক্ষণ নয়। এটিকে ব্যাশ স্ক্রিপ্টে রেখে দেওয়া কিছুটা সহজ করে তোলে।

এটি স্থান নিরাপদ:

#!/bin/bash
#if [ ! "$1" ] ; then
    echo "Usage: $0 <search>";
    exit
fi

find . -type f -print0 \
  | xargs -0 file \
  | grep -P text \
  | cut -d: -f1 \
  | xargs -i% grep -Pil "$1" "%"

4
আপনার স্ক্রিপ্টে বেশ কয়েকটি সমস্যা রয়েছে: ১. যদি বাইনারি ফাইলটির নাম দেওয়া হয় তবে text.binকী হবে? ২. যদি কোন ফাইলনেমে একটি থাকে :?
ঠাকলা

3

এটি করার আরেকটি উপায়:

# find . |xargs file {} \; |grep "ASCII text"

আপনি যদি খালি ফাইলও চান:

#  find . |xargs file {} \; |egrep "ASCII text|empty"

2

এটি সম্পর্কে:

$ grep -rl "needle text" my_folder | tr '\n' '\0' | xargs -r -0 file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable'

আপনি যদি ফাইলের ধরণ ছাড়াই ফাইলের নাম চান তবে কেবল একটি চূড়ান্ত sedফিল্টার যুক্ত করুন।

$ grep -rl "needle text" my_folder | tr '\n' '\0' | xargs -r -0 file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable' | sed 's|:[^:]*$||'

আপনি -e 'type'শেষ grepকমান্ডে আরও বিকল্প যুক্ত করে অপরিবর্তিত ফাইল প্রকারগুলি ফিল্টার আউট করতে পারেন ।

সম্পাদনা:

যদি আপনার xargsসংস্করণ -dবিকল্পটিকে সমর্থন করে তবে উপরের কমান্ডগুলি আরও সহজ হয়ে উঠবে:

$ grep -rl "needle text" my_folder | xargs -d '\n' -r file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable' | sed 's|:[^:]*$||'

বোকা আমাকে। রিকার্সিভ গ্রেপ খেয়াল করেনি। যেমন আমি বুঝতে পেরেছিলাম এটি আসলে বেশ দ্রুত যদিও অনেকগুলি অ্যাপ্লিকেশনে কিছুটা সীমাবদ্ধ। আপনার জন্য +1
এন্টি রাইত্সালি

2

আমি এটি কীভাবে করেছি ...

ঘ। একটি ফাইল সরল পাঠ্য বদ্ধ হয় কিনা তা পরীক্ষা করতে একটি ছোট স্ক্রিপ্ট তৈরি করুন:

#!/bin/bash
[[ "$(file -bi $1)" == *"file"* ]]

ঘ। আগের মত সন্ধান করুন

find . -type f -exec istext {} \; -exec grep -nHi mystring {} \;

আমার ধারণা আপনি বলতে চাইছেন == *"text"* ]]?
ব্যবহারকারী অজানা

আপনি এর পরিবর্তে ম্যাচ-অপারেটর `= ~" পাঠ্য "]]` ব্যবহার করতে পারেন।
ব্যবহারকারী অজানা

2

হিস্টেমনেসের উত্তর নিয়ে আমার দুটি সমস্যা রয়েছে:

  • এটি কেবল পাঠ্য ফাইলের তালিকা করে। অনুরোধ অনুযায়ী এটি আসলে তাদের অনুসন্ধান করে না। আসলে অনুসন্ধান করতে, ব্যবহার করুন

    find . -type f -exec grep -Iq . {} \; -and -print0 | xargs -0 grep "needle text"
    
  • এটি প্রতিটি ফাইলের জন্য একটি গ্রেপ প্রক্রিয়া তৈরি করে, যা খুব ধীর। আরও ভাল সমাধান হয়

    find . -type f -print0 | xargs -0 grep -IZl . | xargs -0 grep "needle text"
    

    বা সহজভাবে

    find . -type f -print0 | xargs -0 grep -I "needle text"
    

    এটি উপরের সমাধানের জন্য 4 সেকেন্ডের তুলনায় কেবল 0.2 সেকেন্ডে লাগে (2.5 জিবি ডেটা / 7700 ফাইল), অর্থাৎ 20x দ্রুত

এছাড়াও, কেউ উদ্ধৃত হয়নি এজি, সিলভার অনুসন্ধান বা এসি - গ্রেপ-এর বিকল্প হিসাবে উল্লেখ করেন নি ited এর মধ্যে একটি উপলব্ধ থাকলে সেগুলি আরও ভাল বিকল্প:

ag -t "needle text"    # Much faster than ack
ack -t "needle text"   # or ack-grep

একটি সর্বশেষ নোট হিসাবে , মিথ্যা ধনাত্মক (বাইনারি ফাইলগুলি পাঠ্য ফাইল হিসাবে নেওয়া) থেকে সাবধান থাকুন । গ্রিপ / এজি / এসিসি ব্যবহার করে আমার ইতিমধ্যে মিথ্যা পজিটিভ ছিল, তাই ফাইলগুলি সম্পাদনা করার আগে ম্যাচ করা ফাইলগুলিকে আরও ভালভাবে তালিকাভুক্ত করুন।


1

যদিও এটি একটি পুরানো প্রশ্ন, আমি মনে করি যে এই তথ্যটি উত্তরগুলি এখানে উত্তরগুলির মানের সাথে যুক্ত করবে।

এক্সিকিউটেবল বিট সেট দিয়ে ফাইলগুলি উপেক্ষা করার সময়, আমি কেবল এই আদেশটি ব্যবহার করি:

find . ! -perm -111

এটিকে পুনরুক্তি থেকে রক্ষার জন্য অন্যান্য ডিরেক্টরিতে প্রবেশ করুন:

find . -maxdepth 1 ! -perm -111

জন্য কোন প্রয়োজন নেই পাইপ কমান্ড প্রচুর শুধু শক্তিশালী প্লেইন মিশে খোঁজ কমান্ড।

  • দাবি অস্বীকার: ওপি ঠিক যা বলেছিল তা নয়, কারণ ফাইলটি বাইনারি কিনা তা পরীক্ষা করে না। এটি, উদাহরণস্বরূপ, বাশ স্ক্রিপ্ট ফাইলগুলি ফিল্টার করবে যা সেগুলি নিজেই পাঠ্য হয় তবে এক্সিকিউটেবল বিট সেট থাকে

এটি বলেছিল, আমি আশা করি এটি কারও উপকারী।


0

আমি এটি এইভাবে করি: 1) যেহেতু অনুসন্ধানের জন্য অনেক বেশি ফাইল (~ 30 কে) রয়েছে, তাই নীচের কমান্ডটি ব্যবহার করে ক্রোনট্যাবের মাধ্যমে আমি প্রতিদিন পাঠ্য ফাইলের তালিকা তৈরি করি:

find /to/src/folder -type f -exec file {} \; | grep text | cut -d: -f1 > ~/.src_list &

2) .bashrc এ একটি ফাংশন তৈরি করুন:

findex() {
    cat ~/.src_list | xargs grep "$*" 2>/dev/null
}

তারপরে আমি অনুসন্ধান করতে নীচের কমান্ডটি ব্যবহার করতে পারি:

findex "needle text"

এইচটিএইচ :)


0

আমি xargs পছন্দ

find . -type f | xargs grep -I "needle text"

যদি আপনার ফাইলের নামগুলি -0 বিকল্পগুলি ব্যবহার করে অদ্ভুত থাকে:

find . -type f -print0 | xargs -0 grep -I "needle text"

0
  • সমস্ত পাঠ / আসকি ফাইলগুলিতে / ইত্যাদি ইন "ইত্যাদি" পাঠ্যটি স্যাচার করার জন্য বাশ উদাহরণ

গ্রেপ এথ0 $ (সন্ধান / ইত্যাদি / -প্রকার এফ-এক্সেক ফাইল {} \; | egrep -i "পাঠ্য | ascii" | কাট-ডি ':' -ফ 1)


0

আমার মতো প্রবর্তকদের জন্য বর্ধিত ব্যাখ্যা সহ একটি সরল সংস্করণ এখানে যারা এক লাইনে কীভাবে একাধিক কমান্ড রাখবেন তা শিখতে চেষ্টা করছেন।

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

// For every file in this directory
// Check the filetype
// If it's an ASCII file, then print out the filename

এই অর্জন করার জন্য, আমরা তিন ইউনিক্স কমান্ড ব্যবহার করতে পারেন: find, file, এবংgrep

find ডিরেক্টরিতে প্রতিটি ফাইল চেক করবে।

fileআমাদের ফাইল টাইপ দেবে। আমাদের ক্ষেত্রে, আমরা 'ASCII পাঠ্য' ফেরত খুঁজছি

grep থেকে আউটপুটে 'ASCII' কীওয়ার্ডটি সন্ধান করবে file

সুতরাং আমরা কিভাবে এক এক লাইনে এই স্ট্রিং করতে পারি? এটি করার একাধিক উপায় রয়েছে তবে আমি দেখতে পেয়েছি যে এটি আমাদের সিউডো কোড অনুসারে করা আমাদের সার্থক করে তোলে (বিশেষত আমার মতো একজন শিক্ষানবিশকে)।

find ./ -exec file {} ";" | grep 'ASCII'

জটিল মনে হচ্ছে, তবে খারাপ না যখন আমরা এটিকে ভেঙে ফেলি:

find ./= এই ডিরেক্টরিতে প্রতিটি ফাইলের মাধ্যমে দেখুন। দ্যfindযে 'অভিব্যক্তি' মিলে যায়, অথবা যাই হোক না কেন কোনো ফাইলের ফাইলের নাম জানতে কমান্ড কপি করে প্রিন্ট পাথ, যা আমাদের ক্ষেত্রে বর্তমান ডিরেক্টরী অথবা পরে আসে./

সবচেয়ে গুরুত্বপূর্ণ বিষয়টি বুঝতে হবে যে সেই প্রথম বিটের পরে সমস্ত কিছু সত্য বা মিথ্যা হিসাবে মূল্যায়ন করা হচ্ছে। যদি সত্য হয় তবে ফাইলটির নাম মুদ্রিত হয়ে যাবে। যদি না হয়, তবে কমান্ডটি এগিয়ে চলেছে।

-exec= এই পতাকাটি অনুসন্ধান কমান্ডের মধ্যে একটি বিকল্প যা আমাদেরকে কিছু অন্যান্য কমান্ডের ফলাফল অনুসন্ধানের অভিব্যক্তি হিসাবে ব্যবহার করতে দেয়। এটি একটি ফাংশন মধ্যে একটি ফাংশন কল করার মত।

file {}= কমান্ডটি ভিতরে ডাকা হচ্ছে findfileকমান্ড একটি স্ট্রিং, যাতে আপনি একটি ফাইল এর filetype: বলে ফেরৎ। নিয়মিতভাবে, এটা ভালো দেখাবে: file mytextfile.txt। আমাদের ক্ষেত্রে, আমরা findকমান্ড দ্বারা যা কিছু ফাইল তাকানো হচ্ছে তা এটি ব্যবহার করতে চাই , তাই আমরা {}একটি খালি ভেরিয়েবল বা পরামিতি হিসাবে কাজ করতে কোঁকড়া ধনুর্বন্ধনী ব্রেসগুলি রেখেছি । অন্য কথায়, আমরা কেবল সিস্টেমের কাছে ডিরেক্টরিগুলির প্রতিটি ফাইলের জন্য একটি স্ট্রিং আউটপুট দেওয়ার জন্য বলছি।

";"= এটি প্রয়োজনীয় findএবং এটি আমাদের -execকমান্ডের শেষে বিরামচিহ্নের চিহ্ন । যদি আপনার চালনার প্রয়োজন হয় তবে আরও ব্যাখ্যাের জন্য 'অনুসন্ধান' এর জন্য ম্যানুয়ালটি দেখুন man find

| grep 'ASCII'= |একটি পাইপ। পাইপ বামে যা আছে তার আউটপুট নেয় এবং ডানদিকে যা থাকে তার ইনপুট হিসাবে এটি ব্যবহার করে। এটি findকমান্ডের আউটপুট নেয় (একটি স্ট্রিং যা একক ফাইলের ফাইল টাইপ) এবং এটি পরীক্ষা করে এটি স্ট্রিং রয়েছে কিনা তা পরীক্ষা করে 'ASCII'। যদি এটি হয়, এটি সত্য ফিরে আসে।

এখন, কমান্ডটি find ./সত্য হলে ডানদিকে ডান দিকের অভিব্যক্তিটি grepসত্য হবে। ভয়েলা।


0

আপনি যদি fileশক্তির সাথে মিলিত দুর্দান্ত সরঞ্জামটি ব্যবহার করে যাদু বাইটগুলি দ্বারা কোনও ফাইল টাইপ সন্ধান করতে আগ্রহী হন তবে এটি কার্যকর findহতে পারে:

$ # Let's make some test files
$ mkdir ASCII-finder
$ cd ASCII-finder
$ dd if=/dev/urandom of=binary.file bs=1M count=1
1+0 records in
1+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.009023 s, 116 MB/s
$ file binary.file
binary.file: data
$ echo 123 > text.txt
$ # Let the magic begin
$ find -type f -print0 | \
    xargs -0 -I @@ bash -c 'file "$@" | grep ASCII &>/dev/null && echo "file is ASCII: $@"' -- @@

আউটপুট:

file is ASCII: ./text.txt

কিংবদন্তি: $ইন্টারেক্টিভ শেল প্রম্পট যেখানে আমরা আমাদের কমান্ডগুলি প্রবেশ করি

আপনি &&কিছু অন্যান্য স্ক্রিপ্ট কল করার পরে অংশটি সংশোধন করতে পারেন বা পাশাপাশি কিছু অন্যান্য জিনিস ইনলাইনও করতে পারেন, অর্থাত্ যদি সেই ফাইলটিতে প্রদত্ত স্ট্রিং থাকে তবে পুরো ফাইলটিকে বিড়াল করুন বা এর মধ্যে একটি দ্বিতীয় স্তরের সন্ধান করুন।

ব্যাখ্যা:

  • find আইটেম যা ফাইল
  • xargsপ্রতিটি আইটেমকে একটি লাইনার bash কমান্ড / স্ক্রিপ্টে লাইন হিসাবে ফিড করুন
  • file ম্যাজিক বাইট অনুসারে ফাইলের ধরণ পরীক্ষা করে, grep ASCII উপস্থিত রয়েছে কিনা তা পরীক্ষা করে, যদি থাকে তবে &&আপনার পরবর্তী কমান্ড কার্যকর করার পরে ।
  • find মুদ্রণ ফলাফল null পৃথক করে , এটিতে ফাঁকা স্থান এবং মেটা-অক্ষরযুক্ত ফাইলের নামগুলি এড়ানো ভাল is
  • xargs-0বিকল্প ব্যবহার করে এগুলি nullপৃথক করে পড়বে,-I @@ প্রতিটি রেকর্ড গ্রহণ করে স্ক্রিপ্টে বাশ করার জন্য পজিশনাল প্যারামিটার / আরগস হিসাবে ব্যবহার করে।
  • --কারণ bashএটি নিশ্চিত করে যে এটির পরে যা আসে তা যুক্তি হলেও এটি এর -মতো শুরু হয়-c যা অন্যথায় ব্যাশ বিকল্প হিসেবে ব্যাখ্যা করা যেতে পারে

আপনার যদি এএসসিআইআই ব্যতীত অন্য কোনও ধরণের সন্ধানের প্রয়োজন হয় তবে কেবল grep ASCIIঅন্য ধরণের, যেমন পছন্দ করুন likegrep "PDF document, version 1.4"


-1
find . -type f | xargs file | grep "ASCII text" | awk -F: '{print $1}'

সমস্ত ফাইল তালিকাভুক্ত করার জন্য ফাইন্ড কমান্ডটি ব্যবহার করুন, তারা পাঠ্য (ট্যারি, কী নয়) যাচাই করতে ফাইল কমান্ড ব্যবহার করুন, পরিশেষে ফিল্টার করতে এবং মুদ্রণের জন্য awk কমান্ডটি ব্যবহার করুন।


-4

এই সম্পর্কে কি

 find . -type f|xargs grep "needle text"

এটি সন্ধান করে না"needle text"
পিওরো

@Navi: শুধুমাত্র উপলব্ধ উদাহরণ ওপি ধারণকারী ফাইল খুঁজে বের করে"needl text"
peoro

4
@ নাভি: এখন এটি টেক্সট ফাইলগুলির জন্য আর সন্ধান করে না: যদি একটি বাইনারি ফাইল থাকে তবে "needle text"এটি পাওয়া যায়
পিওরো

আমিও কেন তোমার কথা শুনছি?
নাভি

4
@ নাভি: আপনার ওয়ান-লাইনার ফাইলের ধরণগুলি পরীক্ষা করে না এবং ফাইলের
নামগুলিতে শ্বেত
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.