কমান্ড কেন “এলএস | ফাইল ”কাজ?


32

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

file ইনপুট হ'ল আরও একটি ফাইলের নাম file filename1 filename2

lsআউটপুট হ'ল ফোল্ডারে ডিরেক্টরি এবং ফাইলগুলির একটি তালিকা, সুতরাং আমি ভেবেছিলাম যে ls | fileকোনও ফোল্ডারে প্রতিটি ফাইলের ফাইলের ধরণটি প্রদর্শন করা উচিত।

আমি যখন এটি ব্যবহার করি তবে আউটপুটটি হ'ল:

    Usage: file [-bcEhikLlNnprsvz0] [--apple] [--mime-encoding] [--mime-type]
        [-e testname] [-F separator] [-f namefile] [-m magicfiles] file ...
    file -C [-m magicfiles]
    file [--help]

fileকমান্ডটি ব্যবহারের ক্ষেত্রে কিছু ত্রুটি ছিল


2
আপনি যদি সরল ব্যবহার করে থাকেন তবে lsএটি নির্দেশ করে যে আপনি বর্তমান ডিরেক্টরিতে থাকা সমস্ত ফাইল fileকমান্ড দিয়ে পরিচালনা করতে চান । ... সুতরাং কেন কেবল না: file *যা প্রতিটি ফাইল, ফোল্ডারের জন্য একটি লাইন দিয়ে উত্তর দেবে।
নুড লারসেন

file *সবচেয়ে স্মার্ট উপায়, আমি কেবল ভাবছিলাম কেন lsআউটপুট ব্যবহার করা কাজ করছে না। সন্দেহ সাফ করা হয়েছে :)
IanC

6
ভিত্তিটি ত্রুটিযুক্ত: "ফাইল ইনপুট ফাইল ফাইল নাম 1 ফাইলের নাম 2 এর মতো আরও ফাইল নামগুলির মধ্যে একটি" এটি ইনপুট নয়। এগুলি হ'ল কমান্ড-লাইন যুক্তি, যেমন @ জন কুগেলম্যান নীচে উল্লেখ করেছেন।
মন্টি হার্ডার

3
স্পর্শকাতরভাবে, পার্সিংls করা সাধারণত একটি খারাপ ধারণা।
কোজিরো

উত্তর:


71

মূল সমস্যাটি হ'ল fileস্ট্যান্ডিনের পরিবর্তে কমান্ড-লাইন আর্গুমেন্ট হিসাবে ফাইলের নাম প্রত্যাশা করে। আপনি যখন লিখবেন ls | fileতখন আউটপুটটি lsইনপুট হিসাবে পাস হচ্ছে file। আর্গুমেন্ট হিসাবে নয়, ইনপুট হিসাবে।

পার্থক্য কি?

  • কমান্ড লাইন আর্গুমেন্ট যখন আপনি একটি কমান্ড পর পতাকা এবং ফাইলের নাম লিখুন, হিসাবে হয় cmd arg1 arg2 arg3। শেল স্ক্রিপ্ট-এ এই আর্গুমেন্ট হিসাবে ভেরিয়েবল পাওয়া যায় $1, $2, $3ইত্যাদি সি আপনি তাদের মাধ্যমে অ্যাক্সেস চাই char **argvএবং int argcআর্গুমেন্ট main()

  • স্ট্যান্ডার্ড ইনপুট, স্টিডিন, ডেটার একটি স্ট্রিম। কিছু প্রোগ্রাম স্ট্যান্ডিনের কাছ থেকে catবা wcপড়ার মতো যখন তাদের কোনও কমান্ড-লাইন আর্গুমেন্ট দেওয়া হয় না। শেল স্ক্রিপ্টে আপনি readএকক লাইন ইনপুট পেতে ব্যবহার করতে পারেন । সিতে আপনি বিভিন্ন বিকল্পের মধ্যে scanf()বা ব্যবহার করতে পারেন getchar()

fileসাধারণত স্টিডিন থেকে পড়া হয় না। এটি প্রত্যাশা করে যে কমপক্ষে একটি ফাইলের নাম আর্গুমেন্ট হিসাবে পাস হবে। এই কারণেই আপনি যখন লেখেন তখন এটি ব্যবহার মুদ্রণ করে ls | fileকারণ আপনি কোনও যুক্তি পাস করেননি।

আপনি ব্যবহার করতে পারে xargsআর্গুমেন্ট মধ্যে stdin রূপান্তর করতে, হিসাবে ls | xargs file। তবুও, যেমন টেরডোন উল্লেখ করেছেন , পার্সিং lsকরা একটি খারাপ ধারণা। এটি করার সর্বাধিক প্রত্যক্ষ উপায় হ'ল সহজ:

file *

2
অথবা fileএর ইনপুট থেকে ফাইলের নামগুলি ব্যবহার করে জোর করে ls | file -f -। এখনও একটি খারাপ ধারণা।
স্পেকট্রা

2
@ ব্রায়াম> এটাই কথা। এবং পাইপ এর স্ট্যান্ডিন lsএর আউটপুট file। চেষ্টা কর.
স্পেকট্রা

4
@ ব্রায়াম> সত্যই এটি অপচয় এবং বিপজ্জনক। তবে এটি কার্যকর হয় এবং যদি ওপি পুনঃনির্দেশগুলি ব্যবহার করতে শিখছে তবে এটি আরও ভাল বিকল্পগুলির সাথে তুলনা করা ভাল। সম্পূর্ণতার জন্য আমি উল্লেখ করতে পারি file $(ls), যা আরও কার্যকরভাবে কার্যকর হয়।
বর্ণা্য

2
আমি মনে করি সমস্ত উত্তর পড়ার পরে আমার সমস্যার একটি বড় ছবি রয়েছে, যদিও আমি মনে করি সত্যই এগুলি বুঝতে আমার আরও পড়া দরকার। প্রথমত, দৃশ্যত পাইপিং এবং পুনঃনির্দেশ ব্যবহার করা আউটপুটটিকে আর্গুমেন্ট হিসাবে পার্স করে না , তবে এসটিডিএন হিসাবে । যা এখনও আরও ভালভাবে বুঝতে আমার আরও পড়তে হবে, তবে একটি পৃষ্ঠপোষক অনুসন্ধানের যুক্তিগুলি মনে হচ্ছে পাঠ্যটিকে একটি অ্যারেতে পাঠ্যকে ছড়িয়ে দেওয়া হয়েছে , এবং কোনও ফাইল বা আউটপুট সম্পর্কিত তথ্য পুল করার মতো STDIN (সমস্ত প্রোগ্রাম ডিজাইন করা হচ্ছে না) এই "পুলিং" দিয়ে কাজ করুন)
আইয়ানসি

3
দ্বিতীয়ত, ব্যবহার ফাইলের নামের একটি তালিকা পরিণত করতে পারবে কারন বিশেষ কিছু অক্ষর আছে যা ফাইলের নামের উপর গৃহীত হয় কিন্তু একটি বিভ্রান্তিকর আউটপুট মধ্যে শেষ করতে পারেন একটি খারাপ ধারণা মত মনে হয়, । যেহেতু এটি ফাইললাইনম এবং ফাইলনামগুলির মধ্যে বিভাজক হিসাবে নিউলাইনগুলি ব্যবহার করে নতুন লাইন এবং অন্যান্য বিশেষ অক্ষর থাকতে পারে , চূড়ান্ত আউটপুট সুনির্দিষ্ট নাও হতে পারে।
আইএনসি

18

কারণ, আপনি যেমনটি বলেছেন, ইনপুটটি ফাইলের নামfile হতে হবে । এর আউটপুটটি অবশ্য পাঠ্য। এটি ফাইলের নামের একটি তালিকা হতে পারে এটি এই সত্যটি পরিবর্তন করে না যে এটি কেবল পাঠ্য এবং হার্ড ড্রাইভে থাকা ফাইলগুলির অবস্থান নয়।ls

আপনি যখন স্ক্রিনে মুদ্রিত আউটপুট দেখেন, আপনি যা দেখেন তা হ'ল পাঠ্য। সেই পাঠ্যটি একটি কবিতা হোক বা ফাইলের নামের তালিকা কম্পিউটারে কোনও পার্থক্য রাখে না। এটি সমস্তই জানেন এটি পাঠ্য। এ কারণেই আপনি lsএমন প্রোগ্রামগুলিতে আউটপুট পাস করতে পারেন যা পাঠ্যকে ইনপুট হিসাবে গ্রহণ করে (যদিও আপনি সত্যই সত্যই বাস্তবে না হওয়া উচিত ):

$ ls / | grep etc
etc

সুতরাং, কোনও কমান্ডের আউটপুট ব্যবহার করার জন্য যা ফাইলের নাম পাঠ্য হিসাবে তালিকাভুক্ত করে (যেমন lsবা find) যে কোনও কমান্ড ফাইল-নাম গ্রহণ করে, আপনাকে কিছু কৌশল ব্যবহার করতে হবে। এর জন্য সাধারণ সরঞ্জামটি হ'ল xargs:

$ ls
file1 file2

$ ls | xargs wc
 9  9 38 file1
 5  5 20 file2
14 14 58 total

আমি আগে বলেছি, যদিও, আপনি সত্যই এর আউটপুট পার্সিং করতে চান না ls। এর মতো findকিছু ভাল ( প্রতিটি ফাইলের নামের পরে নতুনিলের পরিবর্তে print0প্রিন্ট করে \0এবং এ জাতীয় ইনপুট -0নিয়ে কাজ xargsকরতে দেয়; আপনার কমান্ডগুলিকে নিউলাইনযুক্ত ফাইলের নাম দিয়ে কাজ করার কৌশল):

$ find . -type f -print0 | xargs -0 wc
 9  9 38 ./file1
 5  5 20 ./file2
14 14 58 total

বিনা প্রয়োজনে যা করারও এটির নিজস্ব পদ্ধতি রয়েছে xargs:

$ find . -type f -exec wc {} +
 9  9 38 ./file1
 5  5 20 ./file2
14 14 58 total

শেষ পর্যন্ত, আপনি একটি শেল লুপও ব্যবহার করতে পারেন। তবে নোট করুন যে বেশিরভাগ ক্ষেত্রে, xargsআরও দ্রুত এবং আরও কার্যকর হবে। উদাহরণ স্বরূপ:

$ for file in *; do wc "$file"; done
 9  9 38 file1
 5  5 20 file2

একটি পার্শ্ব-ইস্যু যে fileআসলে stdin পড়া বলে মনে হচ্ছে না, যদি না একটি সুনির্দিষ্ট দেওয়া -স্থানধারক: তুলনা file foo, echo foo | fileএবং echo foo | file -; আসলে এটি সম্ভবত ওপিএস ক্ষেত্রে ব্যবহারের বার্তার কারণ (কারণ এটি সত্যিকার অর্থে নয় যে আউটপুটটি ls"কেবল পাঠ্য" নয়, বরং যুক্তির তালিকাটি fileখালি থাকার কারণে)
স্টিল্ড্রাইভার

@ স্টিলড্রাইভার হ্যাঁ এএফআইএকি সব প্রোগ্রামের ক্ষেত্রে এটি ফাইলের প্রত্যাশা এবং ইনপুট হিসাবে পাঠ্য নয় not তারা কেবল স্ট্যান্ডিনকে ডিফল্টরূপে উপেক্ষা করে। মনে রাখবেন যে ফাইলটি echo foo | file -আসলে স্টিন স্ট্রিমে চলবে না । filefoo
টেরডন

আচ্ছা catস্টাডন বাদে অদ্ভুত হাঁস (?!) এর মতো আছে -যখন ফাইল আর্গুমেন্ট দেওয়া ছাড়াও আমার মনে হয়?
স্টিল্ড্রাইভার

3
এই উত্তরটি স্টিডিন এবং কমান্ড লাইন আর্গুমেন্টের মধ্যে পার্থক্যটি ব্যাখ্যা করতে ব্যর্থ হয়েছে এবং তাই, গৃহীত উত্তরের চেয়ে পয়েন্টে থাকা সত্ত্বেও একই কারণে গভীরভাবে বিভ্রান্তিকর।
zwol

5
@terdon আমি মনে করি এটি এ ক্ষেত্রে একটি গুরুতর ত্রুটি। "ফাইল (1) কমান্ড লাইন আর্গুমেন্ট হিসাবে চালিত ফাইলগুলির তালিকা গ্রহণ করে, স্ট্যান্ডার্ড ইনপুট হিসাবে নয়" কেন ওপি-র কমান্ড কাজ করে না তা বোঝার জন্য মৌলিক , এবং সাধারণভাবে শেল স্ক্রিপ্টিংয়ের জন্য এই পার্থক্যটি মৌলিক; আপনি এটিতে চকচকে করে কোনও অনুগ্রহ করছেন না।
zwol

6

শিখেছি যে '|' (পাইপলাইন) এর অর্থ হ'ল আউটপুটটি কোনও কমান্ড থেকে অন্য কোনওটির ইনপুটটিতে পুনর্নির্দেশ করা

এটি আউটপুটটিকে "পুনর্নির্দেশ" করে না, তবে কোনও প্রোগ্রামের আউটপুট নেয় এবং এটি ইনপুট হিসাবে ব্যবহার করে, যখন ফাইল ইনপুট নেয় না তবে ফাইলের নামগুলি আর্গুমেন্ট হিসাবে গ্রহণ করে , যা পরে পরীক্ষা করা হয়। পুনর্নির্দেশগুলি এই ফাইলনামগুলিকে আর্গুমেন্ট হিসাবে পাইপিং করে না, পরে আপনি যা করছেন তা পাস করে না।

আপনি যা করতে পারেন তা হ'ল --files-fromঅপশন সহ একটি ফাইল থেকে ফাইলের নামগুলি পড়ুন যদি আপনার কাছে এমন একটি ফাইল থাকে যা আপনি পরীক্ষা করতে চান এমন সমস্ত ফাইলের তালিকা করে, অন্যথায় কেবল আপনার ফাইলগুলিকে আর্গুমেন্ট হিসাবে পাস করুন pass


6

গৃহীত উত্তরটি কীভাবে পাইপ কমান্ডটি সরাসরি কাজ করে না তা ব্যাখ্যা করে এবং file *কমান্ডের সাহায্যে এটি একটি সহজ, সরল সমাধান সরবরাহ করে।

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

সুতরাং, কমান্ডের find `ls`আউটপুট নেবে এবং lsকমান্ডের আর্গুমেন্ট হিসাবে এটি স্থাপন করবে find। এটি গৃহীত সমাধানের চেয়ে দীর্ঘতর এবং জটিল, তবে এর রূপগুলি অন্যান্য পরিস্থিতিতেও সহায়ক হতে পারে।


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

@ আইএনসি দুর্ভাগ্যক্রমে, বাশ সম্পর্কে বেশিরভাগ বই এবং টিউটোরিয়ালগুলি আবর্জনা, খারাপ অভ্যাসের সাথে কলঙ্কযুক্ত, অবচিত সিনট্যাক্স, সূক্ষ্ম বাগ; (একমাত্র) আস্থাভাজন উল্লেখগুলি ব্যাশ বিকাশকারীরা রয়েছে, এটি হ'ল ম্যানুয়াল এবং ফ্রেইনোডে # ব্যাশ আইআরসি চ্যানেল ( চ্যানেল বিষয়টিতে লিঙ্কযুক্ত সংস্থানগুলিও দেখুন)।
ফায়ার

1
কমান্ড প্রতিস্থাপন ব্যবহার সময়ে সময়ে সত্যিই সহায়ক হতে পারে, কিন্তু এই প্রসঙ্গে এটি বেশ বিকৃত - বিশেষত ls সহ।
জো

এছাড়াও সম্পর্কিত: unix.stackexchange.com/a/5782/107266
ম্যাথ

5

lsপাইপের মাধ্যমে আউটপুটটি 0x0a প্রতিটি লাইনকে পৃথক করে - যেমন একটি লাইনফিড অক্ষর - দিয়ে ডেটার একটি শক্ত ব্লক এবং fileএটি একটি প্যারামিটার হিসাবে পায়, যেখানে এটি একসাথে একাধিক অক্ষরকে কাজ করার প্রত্যাশা করে।

একটি সাধারণ নিয়ম হিসাবে, lsঅন্য কমান্ডগুলির জন্য কোনও ডেটা উত্স তৈরি করতে কখনই ব্যবহার করবেন না - একদিন এটি পাইপ করবে .. rmএবং তারপরে আপনি সমস্যায় পড়ছেন!

একটি লুপ ব্যবহার করা আরও ভাল, যেমন পূর্বে for i in *; do file "$i" ; doneআপনি যে আউটপুটটি চান তা উত্পাদন করে। স্পেস সহ ফাইলের নামগুলির ক্ষেত্রে উদ্ধৃতিগুলি রয়েছে।


8
সহজ: file *;-)
ওয়েন_ ইয়াক্স

3
@IanC আমি সত্যিই যথেষ্ট চাপ সৃষ্টি করতে পারে আউটপুট পার্স lsএকটি হল খুব খুব খারাপ ধারণা । আপনি এটিকে ক্ষতিকারক rmকোনও কিছুতে যেমন পাস করতে পারেন কেবল তাই নয় , এটি গুরুত্বপূর্ণ কারণ এটি কোনও মানক-অ-ফাইলের নামেই ভেঙে যায়।
টেরডন

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

1
না rmস্ট্যান্ডার্ড ইনপুট থেকে ফাইলের নামের নেবেন? আমি মনে করি না. এছাড়াও, একটি সাধারণ নিয়ম হিসাবে ls, ইউনিক্সের শুরু থেকেই ইউনিক্স পাইপলাইন ব্যবহারের জন্য ডেটা উত্সের অন্যতম প্রধান উদাহরণ been এই কারণেই আউটপুটটি টার্মিনাল হওয়ার সময় এটির স্বাভাবিক ডিফল্ট বিন্যাসের বিপরীতে যখন কোনও আউটপুট পাইপ হয় তখন কোনও বৈশিষ্ট্য বা অলংকরণ ছাড়াই এটি একটি সাধারণ এক-ফাইল-নামু-প্রতি-লাইনে ডিফল্ট হয়।
ডেভিডবাক

2
@ দেবীমোরগান এই ওয়েবসাইটটি মূলত একটি অ-প্রযুক্তিগত দর্শকদের লক্ষ্য করে লক্ষ্য করা যায়, সুতরাং এখানে খারাপ অভ্যাসগুলি ছড়িয়ে দেওয়া / উত্সাহিত করা ক্ষতি করে এবং ভাল কিছু করে না। ইউনিক্স.এসই বা অন্যান্য প্রযুক্তি সম্প্রদায়ের উপর, যাদের ব্যবহারকারীরা নিজের পা গুলি না করেই তাদের পায়ের খুব কাছে লক্ষ্য রাখার জ্ঞান / উপায় রাখেন, আপনার বক্তব্য ধরে রাখতে পারে (অন্যান্য অনুশীলনের বিষয়ে) তবে এখানে এটি আপনার মন্তব্যকে স্মার্ট দেখাচ্ছে না।
ফায়ার

4

আপনি যদি কোনও পাইপ ব্যবহার করতে চান তবে সাধারণভাবে একটি ফাইল নাম অনুসরণ করা fileবিকল্পটি ব্যবহার -fকরতে পারেন তবে আপনি স্টিডিন -থেকে পড়ার জন্য একটি একক হাইফেনও ব্যবহার করতে পারেন

$ ls
cow.pdf  some.txt
$ ls | file -f -
cow.pdf:       PDF document, version 1.4
some.txt:        ASCII text

হাইফেন সহ কৌশলটি -প্রচুর স্ট্যান্ডার্ড কমান্ড-লাইন ব্যবহারের সাথে কাজ করে (যদিও এটি --কখনও কখনও হয়), তাই এটি সর্বদা চেষ্টা করার মতো।

হাতিয়ারটি xargঅনেক বেশি শক্তিশালী এবং বেশিরভাগ ক্ষেত্রে কেবলমাত্র প্রয়োজন যদি যুক্তি-তালিকাটি দীর্ঘ হয় ( বিশদগুলির জন্য এই পোস্টটি দেখুন)।


এটা কখন --? আমি কখনই দেখিনি। --সাধারণত "পতাকাগুলির শেষ" সূচক হয়।
জন কুগেলম্যান

হ্যাঁ, তবে আমি এটি প্রোগ্রামার দ্বারা বেশ কয়েকটি উদাহরণ (আব) ব্যবহার করেছেন used আমি ঠিক বুঝতে পারি না কোথায় (আমি করলে একটি মন্তব্য যোগ করব) তবে আমি যখন খুঁজে পেয়েছি তখন আমি যে অভিশাপগুলি বলেছিলাম তা মনে আছে এবং এই অভিশাপগুলি অবশ্যই
এনএসএফডাব্লু

2

এটি নীচের মত কমান্ড ব্যবহার করে কাজ করে

ls | xargs file

এটি আমার পক্ষে আরও ভাল কাজ করবে


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